Skip to content

Infinifi report accuracy: batch-order simulation, Outland context, named-mapping state reads - #378

Merged
spalen0 merged 7 commits into
mainfrom
fix/infinifi-report-accuracy
Sep 25, 2026
Merged

spalen0 merged 7 commits into
mainfrom
fix/infinifi-report-accuracy

Conversation

@spalen0

@spalen0 spalen0 commented Sep 23, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Follow-up to validating the Infinifi Outland chain-143 report (timelock tx 0x4f721e0751fbd99bea32f3682365e9d29a14a37cfc7d03400bfe400b57684f99). All of the report's facts checked out on-chain. It rated the batch HIGH because of several things it said it couldn't verify, and it said the chain-143 USDC route was now open, which isn't true. Three commits:

1. Batch simulation now runs the calls in order (utils/tenderly/simulation.py, ai_explainer._prepare_batch_items)

  • Before, each call in a batch was simulated on its own against the current chain state. In this batch, OutlandFarm.setVault reverted because it needs the oracle that call 1 (Accounting.setOracle) sets.
  • Now the whole batch is sent to Tenderly simulate-bundle in order, from the executor, so each call sees the state left by the earlier ones. That is how executeBatch runs it.
  • Tenderly stops at the first revert. Calls after that point, or every call if the bundle request fails, fall back to independent simulations. The report now labels each result as either Batch simulation or Independent simulation. Failed simulations are still left out of the risk prompt, as before.
  • Checked live on this batch: all 8 calls succeed in order. The same setVault call still reverts when simulated alone.
  • conftest.py now strips TENDERLY_API_KEY. Some existing tests had been making live Tenderly calls when a developer .env was loaded, and the suite now runs in about 9s instead of about 15s.

2. New Infinifi Outland context adapter (utils/llm/infinifi_outland_context.py)

  • addFarms type → its FarmTypes name (2 = MATURITY, an illiquid farm).
  • setOracle → the new oracle's price() scaled by the asset's decimals (for OV-143, 1e18 = parity with USDC).
  • PortalHub.setVault → whether it adds a chain or replaces an existing vault (chains registered before: 8453).
  • Connector calls → reads chainConfig(chainId). For chain 143 the peer, gas limit and selector are all unset, so sends revert until a later setConfiguration sets the peer. The route is not live after this batch.
  • Contracts are identified by the functions in their verified ABI, following EIP-1967 proxies (new utils/llm/abi_exposure.py).

3. Fix: state reads now handle named mapping parameters (utils/on_chain_state.py)

  • mapping(uint256 chainId => bool) didn't match the declaration regex, so the code guessed the type from the setter's arguments. As a result cctpDomainConfigured was reported as uint32. This affected any contract using Solidity ≥0.8.18 named mapping parameters.

Not in scope

  • Safe multisend batches still use skip_simulation=True. The inner CALLs run with msg.sender = the Safe, so the same bundle approach could simulate them when every inner call is operation 0. That's a follow-up.
  • threejane_context has its own copy of the ABI check; it could move to abi_exposure.exposes.
  • The Telegram alert numbers calls from 0 (Call 0), while the report numbers them from 1.

Test plan

  • Unit tests for batch-order vs independent labelling and the fallback (with simulate_bundle mocked), for the Outland adapter, and for named mappings
  • Tests that mocked Tenderly's request/response shapes are removed; only the _merge_balance_override tests stay in tests/test_tenderly_simulation.py
  • Live end-to-end run of explain_batch_transaction on the real batch (not published): one 8-call bundle from the timelock, and all 8 calls show Batch simulation: SUCCESS, including OutlandFarm.setVault, which showed "reverted" in the original report. The re-run rates the batch LOW, says the route is not live yet, and reports cctpDomainConfigured as bool
  • Live mainnet run of the Outland adapter and the bundle simulation on the real batch
  • uv run pytest tests/ (1361 passed), ruff check, ruff format; mypy shows no new errors (the 27 existing ones are unchanged)

🤖 Generated with Claude Code

spalen0 and others added 5 commits September 23, 2026 16:24
…tions

mapping(uint256 chainId => bool) failed the declaration regex and fell
through to the setter-signature guess, so ConnectorCCTP_Chainlink's
cctpDomainConfigured was reported as uint32 instead of bool.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…bundle

Batch calls were simulated independently against current state, so a
call depending on an earlier one in the same batch showed a false
revert (OutlandFarm.setVault needs the oracle set by call 1). Simulate
the batch in order from the executor via simulate-bundle; calls after
a revert, or all calls when the bundle fails, fall back to independent
simulations. Also strip TENDERLY_API_KEY in test isolation so no test
can reach Tenderly live.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Resolves farm type names, the new oracle's scaled price, whether
PortalHub.setVault adds or replaces a chain vault, and whether a
connector route is actually configured (peer / gas limit) so the LLM
does not report an unconfigured route as live.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Those tests only asserted our assumptions about Tenderly's API, which
changes on their side; simulation is verified with a live report run.
Keep the balance-override merge tests, which cover our own logic.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The route status used the pre-batch chainConfig whenever it was already
configured, so a batch that changed or cleared a live route was
reported as leaving the old peer in place. Parse setConfiguration's
peer/selector/gasLimit from the batch (last call per chain wins) and
report the post-batch route alongside the current one.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@spalen0
spalen0 marked this pull request as ready for review September 25, 2026 10:16
@spalen0
spalen0 merged commit ad6d3b2 into main Sep 25, 2026
3 checks passed
@spalen0
spalen0 deleted the fix/infinifi-report-accuracy branch September 25, 2026 10:27
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