Skip to main content
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.
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 chains
  • 0x4300...0000 - Predeploys unique to Blast
You can find a complete listing of Blast’s predeploys here.

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’s Yield 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’s Yield precompile.

Workaround

The current workaround for this issue is to deploy a mock version of the Yield 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 the vm.etch cheatcode.
This method works for both testing and running scripts against Blast. This issue occurs when using 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’s hardhat_setCode RPC method. Just like vm.etch, this method allows us to set the bytecode at an arbitrary address.