How Our Agent Would Have Caught a Critical DEX Vault-Drain Vulnerability Early

A case study on how OpenCode with Claude Opus 4.6, combined with TSA, surfaced a real critical TON DEX exploit path in pre-fix source code.

How Our Agent Would Have Caught a Critical DEX Vault-Drain Vulnerability Early

A single bug was enough to let an attacker drain nearly all funds from a DEX pool.

What matters to us is not claiming priority. This vulnerability was known before our analysis. What matters is something more important for the TON ecosystem: our workflow would have caught it early, directly from source code, before the exploit path turned into a real loss event.

In this case study, we show how our open-source auditing workflow, using OpenCode with Claude Opus 4.6 and our TSA analysis step, surfaced a critical vault-drain condition in a TON DEX codebase. The key lesson is simple: for deep inter-contract vulnerabilities, agent reasoning alone is not enough. The decisive signal came from TSA-driven path exploration.

Why this case matters

Security teams do not need more generic issue lists. They need workflows that can surface real exploit paths in complex smart-contract systems before attackers do.

This case is important for three reasons:

  1. The bug was critical. Under a specific swap path, a user could receive far more value than they put in.
  2. The bug was deep. It sat behind inter-contract message flow and exception handling, which made it difficult to spot by surface-level reading.
  3. The code had already been audited. Human review alone still missed the issue.

That is exactly the gap we are trying to close: not replacing auditors, but giving them an agent-based workflow that scales across the full codebase and goes deeper when manual review stops being enough.

The target we analyzed

We analyzed the pre-fix version of the DEX contracts from GitHub:

CroutonFi contracts (pre-fix commit)

Our starting prompt was intentionally simple:

`contracts` directory contains source code of a DEX on the TON Blockchain. Audit it.

This matters because it reflects the kind of setup a real user would rely on. We did not hard-code the bug, point the agent to a suspicious file, or pre-describe the exploit. The workflow had to inspect the project broadly and build the finding from there.

The public exploit evidence

This was not a hypothetical bug. A public transaction shows the exploit in action:

Exploit transaction on Tonviewer

According to the exploit path, funds were withdrawn from the DEX vault. That makes this case especially useful as a benchmark: we can compare agent-assisted analysis against a vulnerability that mattered in production, not just in a lab.

What the workflow actually did

Our workflow combined two layers:

  • agentic code exploration with OpenCode and Claude Opus 4.6
  • TSA-based deep analysis to explore execution paths and state transitions

At a high level, the process looked like this:

  1. The agent inspected the whole repository. It explored contracts, message handlers, and swap-related logic across the project.
  2. It ran TSA checks. This was the critical step. Manual inspection by the agent alone did not surface the issue because the vulnerability was buried inside a deep inter-contract path.
  3. TSA explored the swap flow symbolically. The key check was whether an arbitrary user could perform a swap that returns more value than they sent.
  4. A violating path was found. TSA identified a path where a user could receive dramatically more than the input amount.
  5. The agent analyzed the intermediate messages. After the path was surfaced, the agent traced the message sequence and identified the root cause in the pool logic.
  6. The result matched the known vulnerability. This gave us a concrete demonstration that the workflow would have flagged the exploit path early on pre-fix code.

This point is worth emphasizing: without TSA, the agent did not find this issue by manual inspection alone. The article is not about a generic “AI read code and found a bug” story. It is about a workflow where broad repository exploration and deep execution analysis reinforce each other.

Why TSA was decisive

Many smart-contract failures do not sit in one obviously dangerous line of code. They emerge from:

  • several contracts exchanging messages,
  • validation checks interacting with fallback behavior,
  • error handling that accidentally suppresses safety conditions,
  • and state transitions that only become dangerous under a specific sequence of actions.

That is exactly what happened here.

A plain code-reading agent can summarize contracts and point at suspicious sections. But in this case, the exploit path was too deep to confidently derive from surface inspection alone. TSA was the turning point because it explored the swap interaction symbolically and asked the economically meaningful question:

Can a random user execute a swap that pays out more value than it receives?

Once such a path existed, the agent had something concrete to investigate. That is a much stronger workflow than asking a model to “look for bugs” in the abstract.

Technical summary of the vulnerability

In simple terms, the issue was this:

if a user attempted to swap a token to itself, the contract could calculate the output amount incorrectly and pay out nearly the entire pool balance.

The vulnerable logic was identified in the agent report at:

  • contracts/pool.func:185-195
  • function: handle_swap_internal

Here is the core finding from the report:

The pool's swap handler wraps calc_y() in a try-catch block to handle potential integer overflows in extremely imbalanced pools. However, this try-catch also catches the error::same_coins_provided exception that calc_y throws when from_token_index == to_token_index.

The dangerous behavior came from a broad catch block:

int y = 0;
try {
    y = calc_y(from_token_index, to_token_index, x, xp);
} catch(_x, _n) {
    y = 0;
}
 
int amount_out = xp.at(to_token_index) - y - 1;

If from_token_index == to_token_index, calc_y throws error::same_coins_provided. But instead of preserving that safety check, the catch block absorbs it and leaves y = 0.

That turns the payout calculation into:

amount_out = xp.at(to_token_index) - 0 - 1

In practice, that means almost the entire pool balance for that token can be paid out.

Attack flow

The agent report reconstructed the exploit path as follows:

  1. The attacker sends a swap message to a vault with from_token = X and to_token = X.
  2. The vault forwards a swap_notification to the pool.
  3. The pool resolves both token indices to the same value.
  4. calc_y(i, i, x, xp) throws error::same_coins_provided.
  5. The catch block absorbs the exception and sets y = 0.
  6. amount_out becomes approximately the entire pool balance.
  7. The pool sends a payout to the vault.
  8. The attacker receives almost all reserves while depositing only a minimal amount.

This is the kind of bug that is easy to underestimate if you only review local logic in isolation. The exploit becomes obvious only when you follow the full message path and state transition sequence.

Root cause

The root cause was not just “same-token swaps are bad.” The root cause was more subtle:

a broad try-catch block accidentally neutralized a critical validation error.

The catch was introduced to handle another class of failure, but it also swallowed a safety check that should have terminated the operation.

This is precisely the kind of issue that broad, automated path exploration is good at surfacing. It is not a textbook signature match. It is an interaction bug between validation logic, error handling, and economic state transitions.

Why this matters for TON security teams

From a product and ecosystem perspective, this case demonstrates three things.

1. Breadth matters

The agent explored the entire project rather than inspecting one manually selected file. Modern TON protocols are multi-contract systems. Real risk often lives in the connections between components, not just in isolated functions.

2. Depth matters

The vulnerability was too deep for manual agent inspection alone. TSA made the difference by exploring the swap path symbolically and surfacing an economically invalid execution trace.

3. Repeatability matters

This was not an anecdotal intuition. The workflow starts from source code, inspects the system broadly, checks meaningful security properties, and produces a concrete finding with a root-cause explanation.

That is the kind of capability the TON ecosystem needs more of: repeatable agent-assisted security infrastructure, not one-off heroics.

What this proves about our approach

We designed this workflow after recognizing a hard truth about smart-contract security: even audited systems can still contain critical exploit paths, especially when vulnerabilities depend on cross-contract behavior and unusual state transitions.

This case validates the direction of our work.

It shows that our approach can:

  • inspect an entire TON smart-contract project,
  • combine LLM-guided exploration with deeper analysis,
  • find economically dangerous execution paths,
  • and explain them well enough for engineers to fix them.

Most importantly, it shows that the value is not in claiming novelty after the fact. The value is building tooling that would have surfaced the issue before exploitation.

How to fix this class of issue

The fix is straightforward: reject same-token swaps before entering the risky calculation path, or ensure the exception handler does not swallow validation errors that must abort execution. The lesson is simple: in financial contracts, fallback and error-handling paths deserve the same scrutiny as the main execution flow.

Try the agent yourself

Our auditing skill is open-source, and anyone can inspect the workflow and run it themselves.

Repository: espritoxyz/ton-ai-audit-skill

If you are building on TON and want broader, deeper security review across your contract system, try the agent and see how it performs on your codebase.

The ecosystem does not need to wait for the next exploit to learn where manual review alone falls short.