Inspiration

DeFi protocols lost roughly $680M to exploits in 2025, and the mix has shifted — 89% of that now comes from protocol-logic bugs, not bridge hacks. Static analyzers and audit tools catch known patterns, but pattern-matching doesn’t prove a bug is exploitable, and it never chains a flaw into a working attack . I wanted to know if an agent can do what a real security researcher does — read unfamiliar code, hypothesize a vulnerability, write a working exploit from scratch, and prove it by actually running it? And once it finds a real bug, could it close the loop and prove its own fix works too?

What it does

Re-entry takes a Solidity contract and runs it through a find → prove → fix → verify lifecycle. Nemotron Nano scans the ABI and source for risk patterns at low cost. Tavily grounds the next step in real historical precedent — actual exploit postmortems, not guesses from memory. Nemotron Ultra then writes a complete, original Solidity exploit contract which gets compiled and executed against a forked EVM sandbox. If it fails, the real on-chain revert reason and fresh Tavily research feed back into the next attempt, bounded and logged. Once an exploit actually drains funds, Ultra generates a minimal patch, the patched contract is redeployed, and the same exploit is replayed to confirm it now fails , while a normal deposit/withdraw still works. Everything is reported through Nemotron Super as an evidence trail, rendered on a live dashboard, and the whole pipeline is benchmarked against a tiered corpus: authored targets, attributed public teaching benchmarks (Ethernaut, Damn Vulnerable DeFi, SmartBugs), and a blind, never-seen-before held-out contract that proves the agent reasons about new code rather than recalling memorized answers.

How we built it

The core loop lives entirely in the orchestrator, talking to Nemotron Nano/Ultra/Super via Nebius Token Factory and to a local Anvil EVM (or, optionally, a Nebius Sandboxes/Contree cloud fork). Solidity only shows up where it structurally must: the target contracts, and the exploit contracts Ultra writes, since reentrancy hijacks execution mid-transaction , something only a contract’s receive() hook can do, not off-chain code. There are two nested retry loops: an inner compile-retry loop that feeds exact solc errors back to Ultra, and an outer execution-retry loop that feeds real revert reasons plus fresh Tavily research back in. A hand-written fallback exploit acts as a safety net if generation fails outright, but it’s tracked and reported separately so a fallback win is never presented as an agent win. The same architecture handles the patch step: generate, redeploy, replay, verify. A benchmark script runs the whole corpus and writes real pass/fail numbers rather than relying on a single cherry-picked demo run.

Challenges we ran into

Early on, every generated exploit reverted with an identical “transfer failed” error across every retry attempt — tracing it back, Ultra’s generated attacker contracts were missing a working receive() hook, since our original prompt treated reentrancy callbacks as optional rather than mandatory. Fixing that meant making the exploit prompt generic and strict rather than target-specific. We also had to be deliberate about scoring: a vault balance dropping isn’t success if it’s just an honest withdrawal, so a run only counts when the attacker contract actually nets funds or a declared invariant breaks. Pinning an exact Solidity version caused spurious compile failures unrelated to the actual exploit logic, burning retries on formatting instead of reasoning. And since Nebius Sandboxes (Contree) is in beta and can return 403 without access, we had to build Local Anvil as a fully independent, equally capable fallback path rather than a degraded one.

Accomplishments that we're proud of

All 13 control contracts correctly report no_exploit_found — zero false positives, which matters as much as the drains themselves. Across the held-out suite, the agent independently generated working exploits for 5 of 13 targets with zero fallback involvement, including cross-function reentrancy and a token-hook vulnerability it had never seen. We publish the 6 misses openly rather than hiding them. The patch-and-verify loop means Re-entry doesn’t just report bugs — it proves its own fixes hold, while confirming legitimate contract functionality still works afterward. And the benchmark is fully reproducible: anyone can rerun scripts/benchmark_pipeline.py and get real numbers, not a story.

What we learned

The biggest lesson was about honesty as a design constraint, separating “agent succeeded” from “fallback succeeded” had to be built into the data structures from the start, or it becomes very easy to accidentally overclaim. I learned a lot about EVM internals and reentrancy mechanics working on the exploit-generation prompt, and about how sensitive an LLM’s code generation is to small constraint omissions (a single soft “you may include receive()” versus a hard requirement was the difference between a working and a silently-failing exploit). We also learned that publishing negative results — misses, modest success rates, limitations in the benchmark corpus — builds more credibility than it costs.

What's next for Re-entry

Expanding the held-out corpus with more real-world-shaped bug classes (flash-loan price manipulation, signature replay, cross-chain bridge logic), moving Contree from optional to the default execution path once it’s out of beta, and exploring whether fine-tuning a Nemotron model on our growing benchmark corpus improves the agent-only success rate beyond 5/13. Longer term, we’d like to pilot Re-entry as a pre-deployment check that protocol teams or audit firms can run against their own contracts before mainnet launch — the same lifecycle, pointed at real (but not-yet-live) code instead of teaching benchmarks.

Built With

  • ai
  • anvil
  • evm
  • factory
  • foundry
  • inference
  • nebious
  • sandbox
  • token
Share this project:

Updates

Submission history