Skip to content

fix(core): use on-chain balance diff for native ETH realized amounts#127

Open
quasystaty1 wants to merge 1 commit into
mainfrom
claude/naughty-mcclintock-2b7a4d
Open

fix(core): use on-chain balance diff for native ETH realized amounts#127
quasystaty1 wants to merge 1 commit into
mainfrom
claude/naughty-mcclintock-2b7a4d

Conversation

@quasystaty1
Copy link
Copy Markdown
Contributor

Summary

  • Native ETH legs (both input and output) don't emit ERC20 Transfer events, so try_from_receipts previously fell back to the simulated strategy::Swap amounts for any native ETH token, making realized profit reflect expected values rather than actual on-chain outcomes
  • Fix queries the signer's ETH balance at block N-1 and N to compute the true transferred amount:
    • ETH in: amount_in = pre_balance − post_balance − gas_cost
    • ETH out: amount_out = post_balance − pre_balance + gas_cost
  • Swap::try_from_receipts is now async and takes a generic P: Provider; Trade::calculate_realized_profit constructs lightweight read-only providers from each chain's rpc_url

What a reviewer should know

  • The balance-diff approach assumes the signer has exactly one transaction in the block — this holds for kuma's serial execution model (slow tx confirmed before fast tx is submitted, each on a different chain)
  • The Tycho router was checked and does not emit any event when delivering native ETH to the receiver (_transferOut calls Address.sendValue with no log), so balance diff is the most practical on-chain approach without debug_traceTransaction
  • ERC20 paths are unchanged — Transfer event parsing is unaffected

Test plan

  • Run an ETH→token or token→ETH trade end-to-end and confirm realized_profit.slow_swap.amount_in / amount_out matches the on-chain balance change
  • Confirm ERC20-only trades (no native ETH legs) are unaffected

🤖 Generated with Claude Code

@quasystaty1 quasystaty1 force-pushed the claude/naughty-mcclintock-2b7a4d branch from 26586ee to 6976521 Compare April 19, 2026 10:57
Native ETH legs don't emit ERC20 Transfer events, so the previous code
fell back to the simulated amounts from strategy::Swap for both input and
output. This caused realized profit to reflect expected values rather than
actual on-chain outcomes.

Now try_from_receipts queries the signer's ETH balance at block N-1 and N:
- ETH in:  amount_in  = pre − post − gas_cost
- ETH out: amount_out = post − pre + gas_cost

The function is now async and takes a generic Provider, which
calculate_realized_profit in Trade constructs from each chain's rpc_url.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@quasystaty1 quasystaty1 force-pushed the claude/naughty-mcclintock-2b7a4d branch from 6976521 to 5a1f203 Compare April 19, 2026 11:04
@quasystaty1 quasystaty1 requested a review from itamarreif April 19, 2026 11:06
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