From 0e0161ad2a85ad53df5701c25067e83d5cfb0db1 Mon Sep 17 00:00:00 2001 From: Quintus Kilbourn Date: Tue, 18 Aug 2026 22:41:59 +0000 Subject: [PATCH 1/5] docs: expand priority updates section (conditional inclusion, best practices, routing against propAMMs) --- docs/api.mdx | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/docs/api.mdx b/docs/api.mdx index 1967eb5..6d25a4d 100644 --- a/docs/api.mdx +++ b/docs/api.mdx @@ -207,17 +207,32 @@ The response contains the transaction hash: ### Priority updates -A priority update is a transaction that BuilderNet includes ahead of other transactions accessing the same state. This can be used by smart contracts to ensure that some interactions are prioritized ahead of others (e.g. for maker vs. taker prioritization). +A priority update is a transaction that BuilderNet includes ahead of other transactions accessing the same state. Market makers use priority updates to run propAMMs (proprietary AMMs): onchain pools whose quotes are refreshed offchain many times per slot. The builder guarantees that takers trade against the freshest posted quote. -Priority update transactions must post data via the [Priority Update Registry](https://github.com/flashbots/priority-update-registry). +**Priority update transactions must post data through the [Priority Update Registry](https://github.com/flashbots/priority-update-registry), which scopes the state an update can write.** These updates can be configured in one of two modes: -* **Top-of-Block:** to land at the **top of the next block** -* **Conditional:** to land only on the condition that another transaction reading the update is also included in the same block. Conditional updates are not guaranteed to be at the top of the block. This is an experimental gas savings feature subject to change. +* **Top-of-Block:** the update lands at the top of the next block, unconditionally. The maker pays gas every block the update lands. +* **Conditional:** the update lands only if a transaction consuming it is also included in the same block. Conditional updates are not guaranteed to be at the top of the block. The maker pays gas only on fills. This is an experimental gas savings feature subject to change. When multiple updates for the same state are available at the time a block is built, the builder will prioritise the latest update. -The mode is set per API key, which can be granted on request (see [How to participate](how-to-participate)). This requirement may be dropped in future. Operators needing both modes can request multiple keys. +The mode is set per API key. This requirement may be dropped in future. Operators needing both modes can request multiple keys. + +Reach out to get API keys (see [How to participate](how-to-participate)). + +#### How conditional inclusion works + +The builder treats a conditional update as consumed when both of the following hold: + +1. **A registered event is emitted.** Each maker registers one or more event signatures (a contract address and an event topic) that identify the event their pool emits when a swap consumes a quote. A conditional update is included only when a transaction in the block emits a matching log. +2. **The update's state is read in a successful call.** The builder traces reads of the update's registered storage slots. Reads made inside subcalls that revert don't count, so a failed fill attempt does not pull the update (and its gas) into the block. + +What this means for integrators: + +- **Makers:** register your consumption events when your conditional API key is provisioned. Without a registered event, conditional updates never land. We plan to upgrade the event registration flow soon. +- **Pool authors:** emit a distinct event on the fill path, not in view or quote paths. +- **Takers and routers:** nothing. Consumption is detected from the fill's logs automatically. #### Endpoints @@ -256,6 +271,11 @@ message PWebsocketQuoteUpdateV1Response { Set the API key in the `Authorization` header when establishing the WebSocket connection. +#### Submission best practices + +- Use one `replacement_uuid` per quoted instrument and increase `replacement_seq_number` monotonically. The builder keeps only the highest sequence number for each uuid, so refresh a quote by replacing it rather than creating a new uuid. +- Target the next block in `block_number` and resend on each new head. Updates for past blocks are dropped. + #### State stream You can subscribe to a read-only stream of the priority update state the builder would apply to the next block. Only priority updates that opt in to publishing are included in the stream. @@ -304,6 +324,12 @@ State overrides can be sent to `0xda7afeed01fe625cf15d187a19f94b45f00b8c5f`. | Bebop | `0xbc60639345dfa607d73b74e88c2d54d8b8ad7cc3` | | Tempest | `0x00000003f1ec2379e79f58e12ec6c4f51ee92149` | +#### Routing against propAMMs + +propAMM liquidity is ordinary onchain liquidity, and any contract can fill against it. The [IPropAMM](https://github.com/lambdaclass/propamm-router-contracts/blob/main/src/interfaces/IPropAMM.sol) interface provides a common way to discover, quote, and swap against propAMMs. The Lambda Class [PropAMMRouter](https://github.com/lambdaclass/propamm-router-contracts) is a reference integration: a single-hop router that quotes and executes against a propAMM and falls back to Uniswap V3 when the propAMM can't fill. + +We are also building just-in-time routing: route selection at block building time, so takers get filled against the freshest propAMM quotes and onchain state. This leads to tighter spreads and lower revert rates. Reach out if you want to integrate early. + --- ### TEE Proof Validation API (aTLS) From 030ebd25475e168c24d28c87c4e7074d16eef488 Mon Sep 17 00:00:00 2001 From: Quintus Kilbourn Date: Tue, 18 Aug 2026 23:00:38 +0000 Subject: [PATCH 2/5] docs: add pricing, clarify stream address roles and PUR posting address --- docs/api.mdx | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/docs/api.mdx b/docs/api.mdx index 6d25a4d..87e014a 100644 --- a/docs/api.mdx +++ b/docs/api.mdx @@ -221,6 +221,10 @@ The mode is set per API key. This requirement may be dropped in future. Operator Reach out to get API keys (see [How to participate](how-to-participate)). +#### Pricing + +Priority update transactions pay no priority fees. Makers are charged a volume fee of 0.1 bps on propAMM volume that settles in BuilderNet-built blocks. Reach out for details. + #### How conditional inclusion works The builder treats a conditional update as consumed when both of the following hold: @@ -308,14 +312,16 @@ Each message is a JSON snapshot describing the aggregated state overrides for th | `slot` | Target slot for the snapshot. | | `blockNumber` | Target block number. | | `timestamp` | Snapshot time (UNIX nanoseconds). | -| `0x…` (address keys) | State overrides are grouped by an address — typically the main propAMM contract. Each maps to a `stateOverride` object describing the storage the builder would apply for priority updates associated with that group. | +| `0x…` (address keys) | The maker's stream address (see the table below). Each maps to a `stateOverride` object describing the storage the builder would apply for that maker's priority updates. | -The `stateOverride` object uses the standard Ethereum state-override format: it maps each contract address to a `stateDiff`, which in turn maps 32-byte storage slots to their 32-byte values. +The addresses in a message play different roles: +- **Top-level keys** are stream addresses: a stable identifier each maker's overrides are published under, typically the maker's main propAMM contract. Use them to select which maker's state to consume. +- **Keys inside `stateOverride`** are the contract accounts whose storage the pending updates modify. The object uses the standard Ethereum state-override format: each account maps to a `stateDiff`, which maps 32-byte storage slots to their 32-byte values. It can be passed directly as the state-override parameter to `eth_call` or `eth_simulateV1` to quote against next-block state. #### propAMM stream addresses -State overrides can be sent to `0xda7afeed01fe625cf15d187a19f94b45f00b8c5f`. +Priority update transactions post their data through the Priority Update Registry at `0xda7afeed01fe625cf15d187a19f94b45f00b8c5f`. | Name | Stream address | | --- | --- | From 1e6ce2b93176d8813c75ce4962d4ee7dd2da1064 Mon Sep 17 00:00:00 2001 From: Quintus Kilbourn Date: Tue, 18 Aug 2026 23:04:19 +0000 Subject: [PATCH 3/5] docs: pricing without rate; add 50 ms taker speed bump --- docs/api.mdx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/api.mdx b/docs/api.mdx index 87e014a..5541728 100644 --- a/docs/api.mdx +++ b/docs/api.mdx @@ -223,7 +223,11 @@ Reach out to get API keys (see [How to participate](how-to-participate)). #### Pricing -Priority update transactions pay no priority fees. Makers are charged a volume fee of 0.1 bps on propAMM volume that settles in BuilderNet-built blocks. Reach out for details. +Priority update transactions pay no priority fees. Makers are charged a volume-based fee on filled trades. Reach out for pricing. + +#### Taker speed bump + +A taker transaction that touches priority-update state is only eligible for inclusion once the builder has held it for at least 50 ms. This protects makers from takers attempting to snipe stale quotes. #### How conditional inclusion works From 1a8a0c09ce1f213a6475a0fec6fd3dd7e4c93bcc Mon Sep 17 00:00:00 2001 From: Quintus Kilbourn Date: Wed, 19 Aug 2026 18:26:37 +0000 Subject: [PATCH 4/5] docs: conditional is the main mode; consumption is event-only; note implementation subject to change --- docs/api.mdx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/api.mdx b/docs/api.mdx index 5541728..e4419d6 100644 --- a/docs/api.mdx +++ b/docs/api.mdx @@ -212,8 +212,10 @@ A priority update is a transaction that BuilderNet includes ahead of other trans **Priority update transactions must post data through the [Priority Update Registry](https://github.com/flashbots/priority-update-registry), which scopes the state an update can write.** These updates can be configured in one of two modes: +* **Conditional:** the update lands only if a transaction consuming it is also included in the same block, so the maker pays gas only on fills. Conditional updates are not guaranteed to be at the top of the block. This is the main way to use priority updates. * **Top-of-Block:** the update lands at the top of the next block, unconditionally. The maker pays gas every block the update lands. -* **Conditional:** the update lands only if a transaction consuming it is also included in the same block. Conditional updates are not guaranteed to be at the top of the block. The maker pays gas only on fills. This is an experimental gas savings feature subject to change. + +The implementation is new and exact behaviour is subject to change. When multiple updates for the same state are available at the time a block is built, the builder will prioritise the latest update. @@ -231,10 +233,7 @@ A taker transaction that touches priority-update state is only eligible for incl #### How conditional inclusion works -The builder treats a conditional update as consumed when both of the following hold: - -1. **A registered event is emitted.** Each maker registers one or more event signatures (a contract address and an event topic) that identify the event their pool emits when a swap consumes a quote. A conditional update is included only when a transaction in the block emits a matching log. -2. **The update's state is read in a successful call.** The builder traces reads of the update's registered storage slots. Reads made inside subcalls that revert don't count, so a failed fill attempt does not pull the update (and its gas) into the block. +Each maker registers one or more event signatures (a contract address and an event topic) that identify the event their pool emits when a swap consumes a quote. A conditional update is included only when a transaction in the block emits a matching log. What this means for integrators: From 45e01088016236700ae72f74aeced706eee04fe4 Mon Sep 17 00:00:00 2001 From: Quintus Kilbourn Date: Wed, 19 Aug 2026 18:34:21 +0000 Subject: [PATCH 5/5] docs: invite feedback --- docs/api.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api.mdx b/docs/api.mdx index e4419d6..cef4efe 100644 --- a/docs/api.mdx +++ b/docs/api.mdx @@ -215,7 +215,7 @@ These updates can be configured in one of two modes: * **Conditional:** the update lands only if a transaction consuming it is also included in the same block, so the maker pays gas only on fills. Conditional updates are not guaranteed to be at the top of the block. This is the main way to use priority updates. * **Top-of-Block:** the update lands at the top of the next block, unconditionally. The maker pays gas every block the update lands. -The implementation is new and exact behaviour is subject to change. +The implementation is new and exact behaviour is subject to change. Feedback welcome. When multiple updates for the same state are available at the time a block is built, the builder will prioritise the latest update.