Placing bundle bids
audience: integrators
Bidding is the offer organism’s job. As a searcher, you submit
sealed bids over bundles that reference the lattice’s current
UnsealedPool[S], and you read the committed auction outcome
from offer::AuctionOutcome.
Open the handles
use offer::Offer;
let bidder = Offer::<Bundle>::bid (&network, Ð_MAINNET.offer).await?;
let mut outcomes = Offer::<Bundle>::outcomes (&network, Ð_MAINNET.offer).await?;
bidder is a Submitter<Bundle>; outcomes is a
Stream<Item = AuctionOutcome>. You need both for a closed loop.
The Bundle datum
Each lattice pins a Bundle type its offer organism auctions
over. The reference shape:
pub struct Bundle {
/// Target slot. offer auctions one outcome per slot.
pub slot: u64,
/// Your bid in the lattice's accounting currency (wei on L1).
pub bid: u128,
/// The transactions you want included, in the order you want them.
pub txs: Vec<Tx2718>,
/// Optional reference into zipnet's UnsealedPool slot content
/// that your bundle depends on (e.g. a backrun target).
pub depends_on: Option<UnsealedRef>,
}
The exact fields are the lattice’s offer::Config
responsibility; offer::Bundle::SCHEMA_TAG folds into the
organism fingerprint, so a version bump is a new organism id,
not a silent upgrade.
Sealing the bid
Bids ride an Offer::<Bundle>::bid stream that is threshold-
encrypted to the offer committee’s published public key before
any committee member sees it. The encryption happens inside
bidder.send; from your point of view the call is just:
let bid_id = bidder.send(Bundle {
slot: target_slot,
bid: 2_500_000_000_000u128, // 2.5 gwei
txs: vec![signed_backrun_tx],
depends_on: Some(UnsealedRef::Slot(target_slot)),
}).await?;
The offer committee unseals the bid inside its state machine at auction close. Until close, no party — not the committee members, not competing searchers, not the lattice operator — sees your bid value.
Bid withdrawal
You can withdraw a bid while the auction is still open, by
sending a BundleWithdraw { bid_id } on the same stream. Once
CloseAuction commits, withdrawals for that slot are rejected.
Outcome
The auction commits one AuctionOutcome per slot. Watch the
stream until you see your target slot:
use futures::StreamExt;
while let Some(outcome) = outcomes.next().await {
if outcome.slot == target_slot {
if outcome.winner == self_addr {
println!("you won slot {} at {} wei", outcome.slot, outcome.bid);
} else {
println!("you lost slot {}; winner {:?}", outcome.slot, outcome.winner);
}
break;
}
}
AuctionOutcome is a committed fact; every offer committee member
has applied the same decision. You do not need to vote or ack;
you only read.
Verifying the auction’s honesty
Offer’s state machine enforces:
- Monotonic slots.
AuctionOutcome[S+1]cannot commit beforeAuctionOutcome[S]. - Unique winner per slot. Exactly one outcome per slot.
- Bid decryption inside apply. Losing bids are never materialised outside the apply step; they are discarded after the winner is picked.
A majority-malicious offer committee can still commit a
non-max-bid winner (see
threat-model — offer).
To detect it, watch tally::Refunds[S]: a legitimate winner
receives a refund proportional to their bid; an offer-committee-
chosen non-winner would receive nothing, and a searcher who
expected to win can escalate. The lattice does not automate
escalation; tally is an audit surface.
Dependencies on unsealed order flow
Backrun-style bundles reference transactions the lattice has
already unsealed for the same slot. UnsealedRef::Slot(S)
instructs the atelier to include your bundle’s txs after any
transactions in UnsealedPool[S]. If the pool is empty for that
slot, the bundle still applies; if your bundle depends on a
specific tx in the pool that is not present, offer’s state
machine rejects the bid at apply time and your send returns
Error::Protocol.
Next reading
- Reading built blocks — verifying the block your winning bid landed in.
- Receiving refunds and attributions — claiming your share of the block’s MEV.
- threat-model — offer — what majority-malicious committees can and cannot do to your bids.