The $257K dTRINITY Loss and How Olympix Would Have Prevented It
Note: dTRINITY did not run Olympix on these contracts before deployment. We ran our analysis AFTER the exploit had already occurred, which lets us show concretely what Olympix would have caught had it been part of the team's pre-deployment workflow. Every finding below was generated from the same contracts the attacker exploited, with no foreknowledge of the incident.
Protocol: dTRINITY (dLEND module)
Network: Ethereum mainnet
Date of incident: March 17, 2026
Amount lost: ~$257,000 in dUSD
Attack class: First-deposit inflation / liquidity index manipulation
Affected market: dLEND-cbBTC reserve (6 days old, extremely low liquidity)
Summary of the Incident
On March 17, 2026, dTRINITY's Ethereum deployment of dLEND, a lending module forked from Aave V3, was drained of approximately $257,300 worth of dUSD. The attacker targeted a newly deployed and sparsely populated cbBTC reserve, manipulating its liquidityIndex through repeated flash loan premium accrual until collateral backed by roughly 0.8 cbBTC reported a value large enough to borrow the entire dUSD lending supply.
The dTRINITY team paused the Ethereum deployment within hours, confirmed the incident publicly, and committed to covering 100% of the bad debt with internal funds. Deployments on Fraxtal and Katana were unaffected, thanks to chain-isolated reserves.
The exploited contract was the cbBTC AToken at 0x504d0eacbf9ea5645a8a9da1b15f3708a5483acc, and the L2Pool contract at 0xfda3a0effe2f3917aa60e0741c6788619ae19e84. The attacker operated from EOA 0x08cfdff8ded5f1326628077f38d4f90df6417fd9.
Background: How the Accounting Works
dLEND inherits Aave V3's index-based share accounting. A supplier's real balance is computed as:
getReserveNormalizedIncome returns the reserve's current liquidityIndex, which grows over time as interest and flash loan premiums accrue. The index is updated on every flash loan repayment using:
This formula is safe when totalLiquidity is meaningfully large. When totalLiquidity approaches zero, even a tiny premium produces an enormous multiplier. That is the exact pathological regime the attacker engineered.
The Attack, Step by Step
The exploit unfolded across two sequential transactions.
The attacker borrowed cbBTC from Morpho Blue via flash loan.
Deposited a small amount into the dLEND-cbBTC reserve, minting 100 scaled shares.
Withdrew 99 of those shares, leaving the reserve in a near-empty state with only 1 scaled share of accounting presence.
Transferred 0.8 cbBTC directly to the aToken contract, bypassing the normal deposit path so the tokens sat in the contract without minting new shares.
Executed repeated flash loans. Every repayment applied the index update formula above. With totalLiquidity artificially depressed, each premium accrual multiplied the liquidityIndex sharply, and after enough iterations it had inflated to roughly 6.22e27 (roughly 6.22x its starting value).
Performed additional deposit/withdraw cycles to clean up residual balances and repaid the flash loan.
At this point, the reserve was in a broken state: the liquidityIndex reported a value completely decoupled from the real cbBTC backing the aToken.
Transaction 2: Collateral Inflation and Extraction
The attacker borrowed cbBTC again from Morpho Blue.
Deposited approximately 7.72 cbBTC into the now-compromised reserve. Because liquidityIndex was inflated, the Pool valued this collateral at a multiple of its true worth during health factor checks.
Used this phantom collateral to borrow approximately 257,300 dUSD from the dLEND-dUSD market, which effectively drained the entire available dUSD lending supply.
Ran additional deposit/withdraw cycles to pull the original cbBTC back out.
Repaid the Morpho flash loan and transferred the dUSD to the attacker's EOA.
Net outcome: the attacker walked away with ~$257K in dUSD, leaving bad debt behind equal to the difference between the inflated collateral valuation and its real economic value.
Root Cause
Three conditions had to hold simultaneously for this attack to succeed, and in the cbBTC market all three did:
No lower bound on reserve liquidity. The reserve could be driven to an almost-empty state without any protective action, and the index update formula did not guard against the degenerate case where totalLiquidity is near zero.
No sanity check on the liquidity index itself.balanceOf multiplied the scaled balance directly by whatever value getReserveNormalizedIncome returned, with no upper bound, no rate-of-change limit, and no invariant tying the result back to the actual underlying balance held by the aToken contract.
A newly listed, sparsely used market. The cbBTC market had only been live for six days. Legitimate supply had not yet accumulated, which is exactly the window an attacker needs for this class of exploit.
The broken invariant is simple to state:
sum(balanceOf(users)) for a reserve should never exceed the real underlying balance held by the aToken contract, modulo accrued-but-unrealized interest from borrowers.
This invariant held in the abstract. The code never enforced it.
What Olympix Found (Post-Exploit Analysis)
dTRINITY did not run Olympix over this codebase before the incident. After the exploit, we pointed BugPocer, our PoC-generating agent, at the exact contracts involved to test a simple question: would Olympix have caught this in a routine pre-deployment scan? The answer is yes, unambiguously.
In a single run (session c08c791f-6db4-4e5e-8d18-7422fe33ceb1, April 21, 2026), BugPocer produced a true positive finding that matches the incident end to end, complete with a runnable test that fails on the exploited contract. No tuning, no hand-holding, no foreknowledge of the attack. This is what Olympix is built to do.
with no sanity check, no upper bound, and no rate-of-change limit on the normalized income. Our finding explicitly described the exploitation path:
Reduce total supply by withdrawing or targeting a low-liquidity market.
Become the dominant supplier.
Use repeated flash loans to inflate getReserveNormalizedIncome() through premium accrual.
Observe that the inflated balanceOf is consumed by the Pool for health factor and collateral checks, enabling borrowing well beyond real collateral value.
That attack plan is a line-by-line description of what actually happened on March 17th.
The Proof of Concept
Critically, we did not stop at a description. BugPocer produced a runnable PoC (balanceOf_liquidity_index_manipulation_inflates_collateral.t.sol) that:
Deploys the real AToken against a mock Pool whose getReserveNormalizedIncome can be set directly.
Mints 1 cbBTC worth of shares to a simulated attacker.
Inflates the index to 10x, 50x, and 100x the baseline.
Asserts the invariant balanceOf(attacker) <= underlyingHeldByAToken.
The assertion fails. Under a 100x inflated index, the attacker's reported balance is 100x the real underlying backing the contract. The same failure occurs for totalSupply(), meaning the accounting is broken at both the per-user and aggregate level. The PoC also demonstrates that even a moderate 10x inflation (far less than the ~6.22x the real attacker actually achieved before extracting) already violates the invariant.
In other words, Olympix did not just pattern-match on risky code. BugPocer mechanically produced the failing invariant, proved it fails under realistic conditions, and named the exact attack primitive: flash-loan-driven index inflation on a low-supply market leading to overstated collateral.
This is the gap most security tools leave open. Static analyzers flag suspicious patterns and leave engineers to decide whether they matter. Manual audits find a subset of bugs but cannot scale to every contract change. Olympix closes the loop: it identifies the vulnerability, writes the exploit as a test, and hands the team a reproducible failure they can fix before merging. The dTRINITY case is a clean demonstration of that loop running on real, exploited code.
How Olympix Would Have Prevented This
The shortest version: had Olympix been in dTRINITY's pre-deployment workflow, the cbBTC market would not have shipped with this bug.
BugPocer's finding lands on an engineer's desk as a failing test. That test is the trigger for a fix. From there, any of the following mitigations would have closed the attack surface, and the failing test would have moved to passing only once the fix was in place:
Minimum liquidity / first-deposit protection on new reserves. Aave V3 addressed this upstream by requiring a non-trivial initial deposit (a "virtual balance" or burned share approach) so that totalLiquidity cannot be driven to near-zero. dLEND's fork lacked this.
Rate-of-change bounds on liquidityIndex. A single transaction should not be able to move the index by multiples. A per-block or per-operation cap would have made the inflation loop infeasible.
Invariant check in balanceOf / health factor computation. The aggregate balanceOf across suppliers should be bounded by the real underlying balance (plus accrued borrower interest). Olympix's PoC encodes exactly this invariant.
Flash loan premium routing. Routing flash loan premiums to the treasury rather than into the reserve's liquidityIndex when totalLiquidity is below a safety threshold neutralizes the inflation vector entirely.
Listing controls for new markets. A freeze on borrowing against freshly listed collateral until it accumulates organic liquidity would have taken cbBTC out of scope for this class of attack during its most vulnerable window.
The decision tree without Olympix: the team did not know the bug existed, so none of these mitigations were on the table. The decision tree with Olympix: the team has a failing test in CI before listing cbBTC, picks one of the fixes above, and the market goes live without exposure. That is the difference between a $257K loss and a non-event.
Timeline
Day 0 (March 11, 2026): cbBTC market listed on dLEND Ethereum.
Day 6 (March 17, 2026): Attacker executes transaction 1 (index manipulation) and transaction 2 (extraction). ~$257K in dUSD drained.
March 17, 2026: DeFiMon Alerts flags the transaction on X. dTRINITY team confirms the incident and pauses the Ethereum deployment.
March 18, 2026: dTRINITY publicly commits to covering 100% of losses from internal funds and begins bad debt repayment within 24 hours.
April 21, 2026 (35 days after the exploit): We ran BugPocer against the already-compromised contracts as a post-incident exercise. It produced a true-positive finding with a reproducing PoC that matches the exploit path precisely, confirming the bug was detectable by automated analysis before deployment.
The Lesson for Web3 Teams
This was not an exotic attack. First-deposit inflation and index manipulation on Aave V3 forks have been public knowledge for over a year, and the fix patterns are well understood. The bug shipped anyway, drained $257K, and burned the dTRINITY team's deployment credibility on Ethereum.
That is the pattern Olympix exists to break. Every protocol team is shipping faster than its audit cadence can keep up with, and forks of battle-tested codebases are the most dangerous category of all. Upstream fixes do not migrate automatically. Forks inherit the assumptions of their source without inheriting its defenses. Manual review is too slow for the surface area a modern DeFi protocol exposes, and pattern-matching tools are too noisy to act on.
Olympix was built for this exact gap. BugPocer reads the contract, identifies the vulnerable invariant, writes a runnable exploit, and gives the team something they can fix and ship the same day. The dTRINITY case demonstrates the full loop on a real exploit, with a real attacker, a real $257K loss, and a finding that would have prevented all of it.
If you are running a DeFi protocol, especially a fork or a fast-moving lending market, the question is not whether Olympix would have caught your last bug. It is whether you want to find your next one before an attacker does.
Run Olympix on your contracts before your next deployment.Book a demo and get your first scan FREE.
What’s a Rich Text element?
The rich text element allows you to create and format headings, paragraphs, blockquotes, images, and video all in one place instead of having to add and format them individually. Just double-click and easily create content.
A rich text element can be used with static or dynamic content. For static content, just drop it into any page and begin editing. For dynamic content, add a rich text field to any collection and then connect a rich text element to that field in the settings panel. Voila!
Headings, paragraphs, blockquotes, figures, images, and figure captions can all be styled after a class is added to the rich text element using the "When inside of" nested selector system.
Follow-up: Conduct a follow-up review to ensure that the remediation steps were effective and that the smart contract is now secure.
Follow-up: Conduct a follow-up review to ensure that the remediation steps were effective and that the smart contract is now secure.
In Brief
Remitano suffered a $2.7M loss due to a private key compromise.
GAMBL’s recommendation system was exploited.
DAppSocial lost $530K due to a logic vulnerability.
Rocketswap’s private keys were inadvertently deployed on the server.
Hacks
Hacks Analysis
Huobi | Amount Lost: $8M
On September 24th, the Huobi Global exploit on the Ethereum Mainnet resulted in a $8 million loss due to the compromise of private keys. The attacker executed the attack in a single transaction by sending 4,999 ETH to a malicious contract. The attacker then created a second malicious contract and transferred 1,001 ETH to this new contract. Huobi has since confirmed that they have identified the attacker and has extended an offer of a 5% white hat bounty reward if the funds are returned to the exchange.