Skip to content

[Draft] PoC for block-consistent balance fetching#4535

Open
ashleychandy wants to merge 5 commits into
cowprotocol:mainfrom
ashleychandy:balance-cache-block-pinning
Open

[Draft] PoC for block-consistent balance fetching#4535
ashleychandy wants to merge 5 commits into
cowprotocol:mainfrom
ashleychandy:balance-cache-block-pinning

Conversation

@ashleychandy

Copy link
Copy Markdown
Contributor

Description

Opening this as a draft PR to validate an issue around balance fetching consistency when processing auction data. This implementation should be considered a proof of concept (PoC) to gather feedback on the proposed approach before refining it into smaller reviewable changes.

Changes

  • Add support for block-pinned balance fetching.
  • Make solvable order balance filtering use the auction block instead of the latest block.
  • Update balance reads and simulations to execute against a specified block.
  • Introduce request deduplication for concurrent balance fetches.
  • Refactor balance cache handling to support block-aware fetching.

@github-actions

Copy link
Copy Markdown

This pull request has been marked as stale because it has been inactive a while. Please update this pull request or it will be automatically closed.

@github-actions github-actions Bot added the stale label Jun 26, 2026
@ashleychandy ashleychandy marked this pull request as ready for review July 2, 2026 22:39
@ashleychandy ashleychandy requested a review from a team as a code owner July 2, 2026 22:40

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the account-balances crate to support block-pinned balance queries, introducing a configurable CachePolicy and in-flight query tracking to prevent duplicate requests. The BalanceFetching trait is updated to accept an optional block_number, which is propagated through the balance simulator and solvable orders cache. The review comments correctly identify a critical issue where a current_block value of 0 (prior to background task initialization) would incorrectly query the genesis block instead of the latest block, and they provide actionable code suggestions to resolve this edge case.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +540 to +548
let fetch_block = self.with_cache(|cache| cache.current_block).unwrap_or(0);

let keys: Vec<InFlightKey> = fetch_queries.iter().map(|q| (q.clone(), None)).collect();
let _guard = InFlightGuard::new(self.balance_cache.clone(), keys);

let results = self
.inner
.get_balances(&fetch_queries, Some(fetch_block))
.await;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

If current_block is 0 (e.g., before the background task has received the first block), fetch_in_flight will query the Ethereum node at block 0 (Some(0)), which is the genesis block. This will return incorrect balances (likely zero) or fail. If current_block is 0, the query should be made with None (latest block) instead of Some(0).

Suggested change
let fetch_block = self.with_cache(|cache| cache.current_block).unwrap_or(0);
let keys: Vec<InFlightKey> = fetch_queries.iter().map(|q| (q.clone(), None)).collect();
let _guard = InFlightGuard::new(self.balance_cache.clone(), keys);
let results = self
.inner
.get_balances(&fetch_queries, Some(fetch_block))
.await;
let fetch_block = self.with_cache(|cache| cache.current_block).unwrap_or(0);
let query_block = if fetch_block == 0 { None } else { Some(fetch_block) };
let keys: Vec<InFlightKey> = fetch_queries.iter().map(|q| (q.clone(), None)).collect();
let _guard = InFlightGuard::new(self.balance_cache.clone(), keys);
let results = self
.inner
.get_balances(&fetch_queries, query_block)
.await;

Comment on lines +676 to +681
let fetch_block = self.with_cache(|cache| cache.current_block).unwrap_or(0);

let new_balances = self
.inner
.get_balances(missing_queries, Some(fetch_block))
.await;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

If current_block is 0 (e.g., before the background task has received the first block), fetch_and_merge will query the Ethereum node at block 0 (Some(0)), which is the genesis block. This will return incorrect balances (likely zero) or fail. If current_block is 0, the query should be made with None (latest block) instead of Some(0).

Suggested change
let fetch_block = self.with_cache(|cache| cache.current_block).unwrap_or(0);
let new_balances = self
.inner
.get_balances(missing_queries, Some(fetch_block))
.await;
let fetch_block = self.with_cache(|cache| cache.current_block).unwrap_or(0);
let query_block = if fetch_block == 0 { None } else { Some(fetch_block) };
let new_balances = self
.inner
.get_balances(missing_queries, query_block)
.await;

@github-actions github-actions Bot removed the stale label Jul 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant