#tx #prefix #vanity #alloy #hash #brute-force #filler

alloy-deadbeef

Brute-force vanity tx prefixes using Alloy

2 unstable releases

new 0.1.0 Dec 16, 2024
0.0.1 Dec 11, 2024

#2 in #alloy

Download history 134/week @ 2024-12-08

134 downloads per month

MIT license

65KB
384 lines

alloy-deadbeef

This crate allows to generate custom, vanity tx hash prefixes:

Vanity tx

It brute-forces the correct hash iterating on gas_limit or value fields until it finds a matching prefix. You can read more about the implemenation details in this blog post.

Usage

cargo add alloy-deadbeef

You can use it as an as an alloy provider filler:

let provider = ProviderBuilder::new()
    .filler(DeadbeefFiller::new(
       "beef".to_string(),
       wallet.clone(),
    ))
    .wallet(wallet)
    .on_http(endpoint().parse()?);

All the transactions sent from this provider will land with a 0xbeef prefix. If you combine it with other fillers, it has to be last one, otherwise hash calculations will be invalid.

Alternatively you can generate a tx object that, once-submitted will have a matching hash prefix:

let tx = TransactionRequest {
    from: Some(account),
    to: Some(account.into()),
    value: Some(U256::ZERO),
    chain_id: Some(chain_id),
    nonce: Some(nonce),
    max_fee_per_gas: Some(gas_price * 110 / 100),
    max_priority_fee_per_gas: Some(GWEI_I),
    gas: Some(21000),
    ..Default::default()
};
let deadbeef = DeadbeefFiller::new("beef".to_string(), wallet.clone())?;
let prefixed_tx = deadbeef.prefixed_tx(tx.clone()).await?;

let provider = ProviderBuilder::new()
    .wallet(wallet)
    .on_http(endpoint().parse()?);

 let _ = provider
    .send_transaction(tx)
    .await?
    .get_receipt()
    .await?;

For prefixes up to 4 characters it's possible to send non payable transaction, because we're iterating on gas_limit instead of value. See this example for details on how to do it.

Alternatively, you can force a specific iteration mode like this:

let mut deadbeef = DeadbeefFiller::new("beef".to_string(), wallet)?;
deadbeef.set_iteration_mode(IterationMode::Value);

Processing time

The table shows the worst case scenario processing times on MBP M2 with 12 CPU cores. Check out the blog post for more details.

Prefix length 99% certainty time
1 547.58µs
2 5.81ms
3 123.86ms
4 1.82s
5 29.62s
6 ~8 minutes
7 ~128 minutes
8 ~34 hours
9 ~23 days

Status

I'd appreciate feedback on how hash crunching speed can be improved. There's a benchmark to easily measure changes in performance:

cargo bench

Dependencies

~36–51MB
~1M SLoC