# Contender Upgrades: April 2025

**URL:** https://collective.flashbots.net/t/contender-upgrades-april-2025/4905
**Category:** Block Builders
**Tags:** article, benchmark, execution-layer, work-in-progress
**Created:** [April 28, 2025, 8:42pm UTC](https://collective.flashbots.net/t/contender-upgrades-april-2025/4905 "2025-04-28T20:42:51Z")
**Posts on this page:** 1
**Page:** 1

<div class="post-metadata">

### Author: ![brock](https://collective.flashbots.net/user_avatar/collective.flashbots.net/brock/32/5_2.png) [@brock](https://collective.flashbots.net/u/brock)
#### Post date: [April 28, 2025, 8:42pm UTC](https://collective.flashbots.net/t/contender-upgrades-april-2025/4905/1 "2025-04-28T20:42:52Z")

</div>

We’ve added a handful of features since [introducing contender](https://collective.flashbots.net/t/introducing-contender/4137):

- scenario definition upgrades
- generate EOAs at scale using `from_pool` declarations
- send bundles in your scenarios
- spam for longer using `spamd`
- spam with the authenticated `engine_` API
  - with optimism support

- contender reports

There’s a lot of info packed behind those bullets, so I’ll break each one down.

## recap

For the unacquainted, [contender](https://collective.flashbots.net/t/introducing-contender/4137) is [a transaction spammer](https://collective.flashbots.net/t/the-execution-layer-testing-loop/4703) that can run a highly customizable variety of onchain scenarios. Users can deploy contracts, define transactions to set up contracts, and define transactions to spam those contracts, all in one file. That file is plugged into contender to execute the scenario on any target chain.

## scenario definition upgrades

### scaled EOAs for spamming

It’s not really realistic for one account to send 500 transactions in a single block. That’s why we added the `from_pool` flag to spam tx definitions; it specifies a pool of accounts that the spam step should pull from when signing a transaction. The number of EOAs generated for each pool corresponds to `--tps` (txs/sec) or `--tpb` (txs/block) in the spam commands, so all scenarios automatically span as many accounts as possible, which gives the appearance of many users interacting with the chain.

Here’s an example of a `spam` definition that uses `from_pool` to assign a pool of spammers:

```toml
[[spam]]
[spam.tx]
to = "{SpamMe3}"
from_pool = "spammers"
signature = "consumeGas(string memory method, uint256 iterations)"
args = ["sstore", "8000"]

```

You can assign different names for different groups, if you want. This can serve to represent the behavior of different groups of people doing different things onchain.

## send bundles

Contender now supports sending bundles over the `eth_sendBundle` RPC method. To declare a bundle in your scenario, use the `[[spam.bundle.tx]]` directive:

```toml

# spam bundle

[[spam]]
[[spam.bundle.tx]]
to = "{SpamMe}"
from_pool = "bluepool"
signature = "consumeGas(uint256 gasAmount)"
...

[[spam.bundle.tx]]
to = "{SpamMe}"
from_pool = "bluepool"
signature = "tipCoinbase()"
...

```

Each `spam.bundle.tx` represents a single transaction in a bundle, which is represented by `[[spam]]`.

You will also need to provide a builder RPC URL (which hosts the `eth_sendBundle` endpoint). To do this, pass the `--builder-url` (`-b`) flag to `spam` or `spamd`.

Here’s an example that targets a local builder setup (provided by [builder-playground](https://github.com/flashbots/builder-playground) and [rbuilder](https://github.com/flashbots/rbuilder)).

```bash
contender spam ./scenarios/spamBundles.toml http://localhost:8545 \
-p $PRK \
--tps 50 \
-b http://localhost:8645

```

See [here](https://github.com/flashbots/contender/blob/main/scenarios/spamBundles.toml) for an example of a scenario that features bundles.

## spamd

`spamd` is short for “spam daemon.” It has all the features of the `spam` command, but it runs multiple spam runs. By default, it runs indefinitely, but this can be limited using `--time-limit` (`-l`). This makes it easier to execute long-term spam runs without worrying about whether you’ll need to change the execution parameters.

> The most likely outcome from running `spamd` with no time limit is that your accounts run out of funds 😉

Each spam run will wait for its transactions to be included, or it will time out. The timeout period can also be configured using `--timeout` (or `-w` or `--wait`). When a spam run times out, a new run will start with freshly-generated transactions.

Example:

```bash
# run 100 batches of 10-block spam runs, each sending 50 txs/sec
cargo run -- spamd ./scenarios/stress.toml $RPC -p $PRK -d 10 --tps 50 -l 100

```

## `engine_` API spamming

We’ve added support for calls to the `engine_` API, so that we can test execution nodes with more control and less overhead. The current implementation relies on the execution node’s mempool (`eth_sendRawTransaction`) to collect the transactions that contender sends. Once contender has sent a batch of transactions, it will call `newPayload` & `forkchoiceUpdated` to trigger block-building in the EL node. This is probably the most simplistic application of the `engine_` API, but it allows us to get a read on how our tx pools are performing, and how quickly our nodes can build blocks.

More work is likely to be done in this area. A replay feature is in the pipeline, where we sync the node back N blocks, and replay the block-building process with the N blocks that have already been built, so we can observe the maximum performance of the target builder under load with full blocks that have been built (using contender spam transactions).

To spam/setup with the auth API, pass the following flags with `spam`, `setup`, or `spamd`:

- `--auth <auth rpc url>`
- `--jwt <jwt file path>`
- `--fcu`

example:

```bash
contender spam ./scenarios/stress.toml http://localhost:8545 \
--jwt ~/test-jwt-secret.txt \
--auth http://localhost:8551 \
--fcu \
--tps 50 -d 1

```

## contender reports

Contender generates chain performance reports that measure the following:

- per-block gas usage & utilization
- peak, and charted over time
- txs per block
- block time stability
- rpc response latency per RPC method
- storage update heatmap
- transaction time-to-inclusion
- per-tx gas usage
- pending transactions over time

These metrics are designed to provide a snapshot of how your target chain acts under specific circumstances; ones imposed by running a contender scenario. We will likely add more metrics over time, so please [make an issue](https://github.com/flashbots/contender/issues/new/choose) if you have ideas for more things we ought to measure!

We’ve been using contender to test the Unichain-Sepolia network — here’s a preview of the results so far:

- [unichain-sepolia\_2025-04-25/report-20-21.html](https://htmlpreview.github.io/?https://github.com/zeroxbrock/official-contender-reports/blob/main/reports/unichain-sepolia_2025-04-25/report-20-21.html)
- [unichain-sepolia\_2025-04-25/report-22-22.html](https://htmlpreview.github.io/?https://github.com/zeroxbrock/official-contender-reports/blob/main/reports/unichain-sepolia_2025-04-25/report-22-22.html)
- [unichain-sepolia\_2025-04-25/report-23-23.html](https://htmlpreview.github.io/?https://github.com/zeroxbrock/official-contender-reports/blob/main/reports/unichain-sepolia_2025-04-25/report-23-23.html)
- [unichain-sepolia\_2025-04-25/report-25-25.html](https://htmlpreview.github.io/?https://github.com/zeroxbrock/official-contender-reports/blob/main/reports/unichain-sepolia_2025-04-25/report-25-25.html)

These reports are very likely to change in the near future – we probably aren’t taking enough measurements. But for now, I hope this gets you excited about contender, and our ultimate goal: _putting nodes to the test!_

If you want to help us make contender the ultimate blockchain testing tool, there’s plenty of ways to get involved. We need help on all kinds of things from CLI & UX design to DX improvements to better data science, and the list goes on.

To get started, check out [contender’s issues](https://github.com/flashbots/contender/issues) page!  
If you’ve been using contender and you have an idea to improve it, please write up a proposal in a [new issue](https://github.com/flashbots/contender/issues/new/choose) and/or contact me directly [@zeroXbrock on X](https://x.com/zeroXbrock).

Lastly, but certainly not least, a big shoutout to our latest community contributors:  
🎉 🙏 🎉

- [deadpine](https://github.com/deadpine)
- [rjected](https://github.com/Rjected)
- [realbigsean](https://github.com/realbigsean)
- [zzzzzzch](https://github.com/zzzzzzch)
- [varun-doshi](https://github.com/varun-doshi)
- [dmarz](https://github.com/dmarzzz)
- [sukoneck](https://github.com/sukoneck)

Thank you all. Every contribution makes a difference.
