Skip to content

Conversation

@fgimenez
Copy link
Member

@fgimenez fgimenez commented Dec 31, 2025

Closes CHAIN-387

Fixes flip order issues for both ask->bid and bid->ask scenarios.

  • ask->bid
    When an ask flip order is filled, the maker receives quote tokens rounded down. The flip logic then tried to place a bid using the original base amount, which could require more quote for escrow than was actually received.

With the changes in this PR we apply consistent rounding when calculating the flip amount:

let quote_received = base_to_quote(fill_amount, order.tick(), RoundingDirection::Down);
let flip_amount = quote_to_base(quote_received, order.flip_tick(), RoundingDirection::Down);

By rounding down consistently, the flip order is sized to what can actually be escrowed with received funds.

  • bid -> ask

When a bid flip order is partially filled and the maker withdraws their internal balance, the subsequent fill would still create a flip order by using tokens just credited from the current fill. This violated the design intent that flip orders should only use pre-existing internal balance.

In this case we use order.amount() instead of fill_amount:

let flip_amount = if order.is_bid() {
    order.amount()  // Use original amount, not fill_amount
} else {
    // ask->bid rounding-aware calculation
};

This ensures the flip requires the original order amount for escrow, which won't be available if the maker withdrew after partial fills.

@fgimenez fgimenez added C-Bug An unexpected or incorrect behavior A-precompile Related to precompiles C-audit Related to audit findings labels Dec 31, 2025
@vercel
Copy link

vercel bot commented Dec 31, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Review Updated (UTC)
tempo-docs Ignored Ignored Preview Dec 31, 2025 4:50pm

@fgimenez fgimenez requested a review from danrobinson December 31, 2025 11:37
@fgimenez fgimenez force-pushed the fgimenez/flip-order-failures-auto-reduce branch from 8d1bd8f to 64383d7 Compare December 31, 2025 12:11
Comment on lines 698 to 708
// Ask filled: maker received quote tokens (rounded down)
// Flip creates bid: escrows quote tokens (rounded up)
// Calculate max base affordable with the quote received
let quote_received =
base_to_quote(fill_amount, order.tick(), RoundingDirection::Down)
.ok_or(TempoPrecompileError::under_overflow())?;

// Calculate how much base can be bought with quote_received at flip_tick
// Round down to ensure we don't exceed available quote
quote_to_base(quote_received, order.flip_tick(), RoundingDirection::Down)
.ok_or(TempoPrecompileError::under_overflow())?
Copy link
Collaborator

Choose a reason for hiding this comment

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

IIUC, this implies that the flip order will (very) slowly decrease in quantity as it flips? It might be useful to document this.

Copy link
Member Author

Choose a reason for hiding this comment

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

yep done here 7abcf27

@fgimenez
Copy link
Member Author

fgimenez commented Jan 1, 2026

closing in favor of #1824

@fgimenez fgimenez closed this Jan 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-precompile Related to precompiles C-audit Related to audit findings C-Bug An unexpected or incorrect behavior

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants