---
title: "Submitting a block to Ethereum"
url: "/docs/block-builders/customizing-a-builder/submitting-a-block-to-ethereum/index.md"
description: "How to submit rollup blocks to Ethereum using EIP-4844 blobs and the Zenith contract."
---
# Submitting a Block to Ethereum

Rollup blocks are submitted to the host chain by calling the Zenith [`submitBlock`](https://github.com/init4tech/zenith/blob/37f386a8465d97f40e3233971c7a7868bbd4e4d9/src/Zenith.sol#L105) function, attaching transaction data in a 4844 blob.

## Code Flows

These examples assume one has already [chosen a set of transactions and bundles](/docs/block-builders/customizing-a-builder/getting-transactions-and-bundles-for-a-block/index.md), and [gotten a co-signature from the Sequencer API](/docs/block-builders/customizing-a-builder/getting-a-sequencer-signature/index.md).

> **Note:** The [builder example](https://github.com/init4tech/builder/tree/main/src/tasks/submit) has a submission process without host fills that can be referenced for blob construction.

For blocks with host fill components, builders should use a multi-call contract to do the following:

- Call `submitBlock` as described below
- Pass each permit2 blob to the Passage contract's `fillPermit2` method

## Creating the Blob Transaction

1. [Transform](https://github.com/init4tech/zenith-rs/blob/ab25a183ad5c8b5c2c39aa2443e89380240423f2/crates/builder/src/tasks/submit.rs#L105C9-L111C11) the [`SignResponse`](https://docs.rs/zenith-types/latest/zenith_types/struct.SignResponse.html) into a [`Zenith::BlockHeader`](https://docs.rs/zenith-types/latest/zenith_types/Zenith/struct.BlockHeader.html).

   ```rust
   let header = Zenith::BlockHeader {
       hostBlockNumber: resp.req.host_block_number,
       rollupChainId: U256::from(self.config.ru_chain_id),
       gasLimit: resp.req.gas_limit,
       rewardAddress: resp.req.ru_reward_address,
       blockDataHash: in_progress.contents_hash(),
   };
   ```

2. [Encode](https://github.com/init4tech/zenith-rs/blob/ab25a183ad5c8b5c2c39aa2443e89380240423f2/crates/builder/src/tasks/submit.rs#L85) the [`submitBlock`](https://github.com/init4tech/zenith/blob/37f386a8465d97f40e3233971c7a7868bbd4e4d9/src/Zenith.sol#L105) transaction data from the `BlockHeader` & the Sequencer's `Signature` from the `SignResponse`

   ```rust
   let data = Zenith::submitBlockCall { header, v, r, s, _4: Default::default() }.abi_encode();
   ```

   > **Note:** The final unnamed `bytes` parameter should be an empty bytes string

3. [Encode](https://github.com/init4tech/zenith-rs/blob/da819327dba6e62a084cd99625e561811a31f12f/crates/builder/src/tasks/block.rs#L71) the transactions into a 4844 blob sidecar containing the rlp-encoded transactions.

   ```rust
   pub fn encode_blob(&self) -> SidecarBuilder {
       let mut coder = SidecarBuilder::default();
       coder.ingest(self.encode_raw());
       coder
   }
   ```

   > **Note:** Signet blobs use the alloy [`SimpleCoder`](https://docs.rs/alloy-consensus/latest/alloy_consensus/struct.SimpleCoder.html) blob encoding scheme. This may change in the future.

4. [Attach](https://github.com/init4tech/zenith-rs/blob/da819327dba6e62a084cd99625e561811a31f12f/crates/builder/src/tasks/submit.rs#L118) the blob sidecar to a [`TransactionRequest`](https://docs.rs/alloy-rpc-types/latest/alloy_rpc_types/struct.TransactionRequest.html).

   ```rust
   let tx = TransactionRequest::default().with_blob_sidecar(sidecar).with_input(data);
   ```

5. Fill in remaining transaction details (including the calldata, which must contain the encoded `submitBlockCall` above).

   > **Note:** If using a multi-call contract, the input to the multi-call must send the encoded `submitBlockCall` to the `Zenith` contract.

6. Submit the constructed transaction to Ethereum.

   > **Warning:** It is **CRITICALLY IMPORTANT** to use a private transaction relay to submit blocks coupled with fills. Leaking fill transactions or signed permit2 fills may result in loss of building privileges.

