Predeployed and precompiled contracts, or simply predeploys and precompiles, are a special class of contracts at predetermined addresses that come with Blast out-of-the-box without ever having been explicitly deployed by an EOA. These contracts implement core functionalities such as the L2 side of bi-directional message passing between Blast and Ethereum, as well as the bridging logic built on top of it. They are also unique in that Blast’s node can interface directly with them to initiate transactions in response to messages received from Ethereum mainnet. In this article, we will identify the differences between predeploys and precompiles, examine how precompiles can cause problems during local development and testing, and provide examples of workarounds for these issues.Documentation Index
Fetch the complete documentation index at: https://metalayerlabs.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
Predeploys and precompiles are not unique to Blast. Most of Blast’s precompiles are common across all EVM chains, and most of its predeploys are common to all OP Stack chains.
Predeploys
Predeploys are smart contracts with bytecode deployed to predetermined addresses at genesis. You can identify a predeploy by its common addressing pattern:0x4200...0000- Predeploys shared with other OP Stack chains0x4300...0000- Predeploys unique to Blast
Precompiles
Precompiles are accessed at predetermined addresses but are implemented directly within the execution client. As a result, there is no bytecode deployed to precompile addresses. For example, when calls are made to Blast’sYield contract at 0x0000...0100, Blast’s execution client (Blast Geth) uses an internal Go implementation for execution rather than any bytecode deployed at that address.
Local Development
The Problem
When running scripts or tests on a forked execution environment, the chain state—including the bytecode of existing contracts—is copied into the testing environment. Interacting with predeploys when forking Blast is generally not an issue since their bytecode is copied over like any other contract. However, because precompiles lack bytecode at their addresses, any attempts to interact with them will revert. New Blast builders often encounter this issue during fork tests or when deploying contracts that configure or claim native ETH yield, as these operations interact with Blast’sYield precompile.
Workaround
The current workaround for this issue is to deploy a mock version of theYield predeploy to 0x0000000000000000000000000000000000000100 within the local environment. This YieldMock contract doesn’t need to fully implement the Yield precompile; it simply needs to satisfy the IYield interface so that calls to it do not revert.
The following is an example of a minimal YieldMock contract that satisfies the IYield interface.
Foundry
Using Foundry, you can deploy bytecode to an arbitrary address using thevm.etch cheatcode.
forge script, because Foundry attempts local and forked simulations before broadcasting any transactions.
The --skip-simulation flag can be used to opt out of forked simulations, but local simulation cannot be skipped.
When using
vm.etch with forge script, ensure that you are not calling vm.etch in any code that will be broadcasted.Hardhat
Builders using Hardhat can use the same approach with the Hardhat node’shardhat_setCode RPC method. Just like vm.etch, this method allows us to set the bytecode at an arbitrary address.