Skip to content

Commit

Permalink
fix: Override blockhash in zk context (#400)
Browse files Browse the repository at this point in the history
  • Loading branch information
Jrigada authored May 31, 2024
1 parent c4dc92b commit cd95784
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 1 deletion.
19 changes: 19 additions & 0 deletions crates/zksync/core/src/vm/tracer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ const SELECTOR_SYSTEM_CONTEXT_BLOCK_TIMESTAMP: [u8; 4] = hex!("796b89b9");
/// Selector for `baseFee()`
const SELECTOR_BASE_FEE: [u8; 4] = hex!("6ef25c3a");

/// Selector for retrieving the blockhash of a given block.
/// This is used to override the current `blockhash()` to foundry test's context.
///
/// Selector for `getBlockHashEVM(uint256)`
const SELECTOR_BLOCK_HASH: [u8; 4] = hex!("80b41246");

/// Represents the context for [CheatcodeContext]
#[derive(Debug, Default)]
pub struct CheatcodeTracerContext<'a> {
Expand Down Expand Up @@ -286,6 +292,19 @@ impl<S: Send, H: HistoryMode> DynTracer<S, SimpleMemory<H>> for CheatcodeTracer
}
}

// Override blockhash
if let Opcode::FarCall(_call) = data.opcode.variant.opcode {
let calldata = get_calldata(&state, memory);
let current = state.vm_local_state.callstack.current;

if current.code_address == SYSTEM_CONTEXT_ADDRESS &&
calldata.starts_with(&SELECTOR_BLOCK_HASH)
{
self.farcall_handler.set_immediate_return(rU256::ZERO.to_be_bytes_vec());
return
}
}

if let Some(delegate_as) = self.call_context.delegate_as {
if let Opcode::FarCall(_call) = data.opcode.variant.opcode {
let current = state.vm_local_state.callstack.current;
Expand Down
27 changes: 26 additions & 1 deletion zk-tests/src/Basic.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ contract BlockEnv {
basefee = block.basefee;
chainid = block.chainid;
}

function ZkBlockhash(uint256 _blockNumber) public view returns (bytes32) {
return blockhash(_blockNumber);
}
}

contract ZkBasicTest is Test {
Expand All @@ -28,13 +32,17 @@ contract ZkBasicTest is Test {

uint256 forkEra;
uint256 forkEth;
uint256 latestForkEth;

function setUp() public {
forkEra = vm.createFork("mainnet", ERA_FORK_BLOCK);
forkEth = vm.createFork(
"https://eth-mainnet.alchemyapi.io/v2/Lc7oIGYeL_QvInzI0Wiu_pOZZDEKBrdf",
"https://eth-mainnet.alchemyapi.io/v2/Lc7oIGYeL_QvInzI0Wiu_pOZZDEKBrdf", //trufflehog:ignore
ETH_FORK_BLOCK
);
latestForkEth = vm.createFork(
"https://eth-mainnet.alchemyapi.io/v2/Lc7oIGYeL_QvInzI0Wiu_pOZZDEKBrdf" //trufflehog:ignore
);
}

function testZkBasicBlockNumber() public {
Expand Down Expand Up @@ -88,6 +96,14 @@ contract ZkBasicTest is Test {
be.chainid() == block.chainid,
"propagated block chainid is the same as current"
);
require(
be.ZkBlockhash(block.number) == blockhash(block.number),
"propagated blockhash is the same as current"
);
require(
be.ZkBlockhash(block.number) == bytes32(0),
"blockhash mismatch"
);

be = new BlockEnv();
require(
Expand Down Expand Up @@ -140,4 +156,13 @@ contract ZkBasicTest is Test {
"propagated block basefee is the same as before"
);
}

function testZkBlockhashWithNewerBlocks() public {
vm.selectFork(latestForkEth);
BlockEnv be = new BlockEnv();
require(
be.ZkBlockhash(block.number) == blockhash(block.number),
"blockhash mismatch"
);
}
}

0 comments on commit cd95784

Please sign in to comment.