Crafting Transactions
The simplest way to craft transactions is by using the TransactionRequest builder with the help of the TransactionBuilder. The TransactionBuilder
provides a convenient interface for setting transaction fields such as recipient, value, gas, data and more, allowing you to easily construct different types of transactions whether you're sending ETH, calling a contract, or deploying a new contract.
Here's a short example of crafting a simple ETH transfer request:
use alloy::{
rpc::types::TransactionRequest,
network::TransactionBuilder,
primitives::{address, U256},
};
let tx = TransactionRequest::default()
.with_to(address!("0x1234567890abcdef1234567890abcdef12345678"))
.with_value(U256::from(1000));
This approach ensures your transaction is correctly structured and ready to be signed and submitted to the network. Note that we didn't set from
, nonce
, chain_id
, or any gas related fields. These necessary fields are automatically filled by the RecommendedFillers
before dispatch making our code less verbose. You can find more details about a transactions lifecycle and RecommendedFillers
in the Transaction Lifecycle post.
Building specific transaction types
Alloy supports building a transaction request for all types of transactions via the same TransactionRequest
builder we used above for crafting an ETH transfer. By default, the TransactionRequest
attempts to build an EIP1559 transaction. However, you can also build other types of transactions by specifying the required type-specific fields or using specialized builders:
- Legacy transactions: Set the
gas_price
field. Omit EIP-1559 fields likemax_fee_per_gas
andmax_priority_fee_per_gas
. - EIP-2930 transactions: Set the
access_list
field. This creates an access-list transaction. - EIP-1559 transactions: Set the
max_fee_per_gas
andmax_priority_fee_per_gas
fields. Omit thegas_price
field. - EIP-4844 transaction: Use the
TransactionBuilder4844
to set blob specific fields using the.with_blob_sidecar(..)
method. - EIP-7702 transaction: Use the
TransactionBuilder7702
to set the authorization list using the.with_authorization_list(..)
method.
Legacy Transactions
Setting the gas_price
field hints the builder to construct a legacy transaction i.e TxType = 0
.
use alloy::{
rpc::types::TransactionRequest,
network::TransactionBuilder,
primitives::{address, U256},
};
let tx = TransactionRequest::default()
.with_to(address!("0x1234567890abcdef1234567890abcdef12345678"))
.with_value(U256::from(10000))
.with_gas_price(U256::from(100));
Find the full example here.
EIP-2930 Transaction
EIP-2930 access list transaction (TxType = 1
) can be built by setting the access_list
field. You can learn more about the AccessList
here.
use alloy::{
rpc::types::TransactionRequest,
network::TransactionBuilder,
primitives::{address, U256},
};
// ..snip..
let tx = TransactionRequest::default()
.with_to(address!("0x1234567890abcdef1234567890abcdef12345678"))
.with_value(U256::from(100))
.with_input(calldata)
.with_access_list(access_list);
Find the full example here.
EIP-1559 Transaction
By default the builder attempts to construct an EIP1559 transaction (TxType = 2
). You can make this explicit by specifiying the priority gas fields.
use alloy::{
rpc::types::TransactionRequest,
network::TransactionBuilder,
primitives::{address, U256},
};
let tx = TransactionRequest::default()
.with_to(address!("0x1234567890abcdef1234567890abcdef12345678"))
.with_value(U256::from(10000))
.with_max_fee_per_gas(1000)
.with_max_priority_fee_per_gas(100);
Find the full example here.
EIP-4844 Transaction
EIP-4844 transactions (TxType = 3
) are specific to Ethereum mainnet. One can build such transactions using the TransactionBuilder4844
struct. This builder provides methods to set blob specific fields using the .with_blob_sidecar(..)
method.
use alloy::{
rpc::types::TransactionRequest,
network::{TransactionBuilder, TransactionBuilder4844},
primitives::{address, U256},
};
// ..snip..
let tx = TransactionRequest::default()
.with_to(address!("0x1234567890abcdef1234567890abcdef12345678"))
.with_value(U256::from(1000))
.with_blob_sidecar(blob_sidecar);
Find the full example here.
Example: EIP-7702 Transaction
EIP-7702 transaction (TxType = 4
)
use alloy::{
rpc::types::TransactionRequest,
network::{TransactionBuilder, TransactionBuilder7702},
primitives::{address, U256},
};
// .. snip..
let tx = TransactionRequest::default()
.with_to(address!("0x1234567890abcdef1234567890abcdef12345678"))
.with_value(U256::from(1000))
.with_authorization_list(authorization_list);
Find the full example here.
Inspecting Transaction Type Output
The TransactionBuilder
provides methods inspect the transaction type while building it:
.complete_type(tx_type: TxType)
: Check if all necessary keys are present to build the specified type, returning a list of missing keys..output_tx_type()
: Returns the transaction type that this builder will attempt to build. This does not imply that the builder is ready to build..output_tx_type_checked()
: Like.output_tx_type()
, ReturnsNone
if the builder is not ready to build.