Renegade's $209K Loss and How Olympix Would Have Prevented It
Date: May 10, 2026
Chain: Arbitrum
Loss: about $209K drained, of which about $190K was returned and 20,000 USDC kept as a bounty
Class: unprotected initializer on an upgradeable dark pool proxy
At 08:27:23 UTC on May 10, 2026, a single transaction on Arbitrum deployed three contracts, made one of them the owner of Renegade's V1 dark pool proxy, and pulled 26 token balances out of the pool in the same breath. The haul included 104,383.59 USDC, 10.28 WETH, 0.35 WBTC and more than 9,400 PENDLE, about $209K in total by the estimates of both Blockaid and Renegade itself.
Eight hours later most of it came back. Renegade sent the attacker an on-chain offer to treat the drain as a whitehat disclosure if 90% of the assets were returned, and within about twenty minutes of that message the attacker sent every major token back to a Renegade wallet, keeping 20,000 USDC as the bounty along with a handful of small tokens. Renegade said affected users would be made whole. The protocol's actual cost was that 20,000 USDC, and the reason it had to pay anything at all was a proxy that let a stranger walk in and take the keys.
A Dark Pool Behind a Proxy
Renegade is a dark pool, a trading venue where orders stay hidden until they match. Its V1 Arbitrum deployment kept user balances in a single contract, an EIP-1967 upgradeable proxy that Blockscout shows was deployed in September 2024. A proxy like this holds the money and the storage, and it forwards every call to a separate implementation contract that holds the logic. Whoever controls the proxy decides which logic it runs, so in practice that party controls everything the proxy holds.
Upgradeable proxies don't run a constructor the way ordinary contracts do. They rely on an initializer, a function that sets up the proxy's storage once, including who its owner is, and that's supposed to lock itself after the first call. If that first call never happens, or the lock never takes, the initializer stays open, and whoever calls it first gets to write the setup.
How Renegade Explained the Gap
In its statement on X the same day, Renegade confirmed that the issue was isolated to the V1 Arbitrum deployment, that its V1 Base, V2 Arbitrum and V2 Base deployments were safe, and that all infrastructure supporting trades against the affected pool had been paused. According to Cointelegraph's report, Renegade traced the root cause to two things working together: deployment code that didn't assign the contract an explicit owner, and a faulty migration in an April 2025 software update. Together they let anyone rewrite the contract tied to the V1 Arbitrum dark pool. Renegade also said only about 7% of its trading volume went through that pool and that it would publish a full root-cause analysis. As of November 6, 2026, we hadn't found that analysis published.
Blockaid's alert described the same weakness from the attacker's side. An unprotected initializer on the dark pool proxy let the attacker inject its own logic and delegatecall it in the proxy's storage. Delegatecall is how a proxy borrows code: it runs the other contract's instructions as if they were its own, with its own balances and its own storage. Once the attacker could choose what code ran inside the proxy, the proxy's tokens were the attacker's to move.
One Transaction, a New Owner
The on-chain record lines up with that account. The attacker's wallet sent one contract-creation transaction that produced three new contracts. During that transaction, the dark pool proxy emitted an OwnershipTransferred event naming the first of those freshly created contracts as its new owner, and a FeeChanged event from the proxy appears in the same logs. Arbiscan lists 26 ERC-20 transfers from the proxy to the attacker's wallet in that same transaction, and Blockaid's alert counts 27 tokens drained.
There was no flash loan, no price manipulation and no clever math. The attacker didn't have to beat any check, because the check that should have stood in front of the setup function wasn't doing its job. The money moved because the proxy, as far as its own storage was concerned, now belonged to someone else.
Twenty Minutes to Give It Back
At 16:29:02 UTC, an address used by Renegade sent the attacker an on-chain message. It acknowledged the vulnerability, offered to treat the drain as a whitehat disclosure, and asked for 90% of the assets to be returned to a Renegade wallet. According to Cointelegraph, the message also warned of possible civil or criminal action if the attacker didn't cooperate.
The returns started at 16:49:02 UTC with the WBTC and finished at 16:53:54 UTC with the USDC. In that window the attacker's wallet sent back the full WBTC, WETH, PENDLE, LDO, CRV, LINK, AAVE, UNI, GMX, ARB, GRT, ZRO, ETHFI, LPT, XAI, COMP, RDNT and USDT0 balances it had taken. The USDC came back short by exactly 20,000, with 84,383.59 USDC returned out of 104,383.59. Seven small tokens, which Arbiscan shows at little or no market value, stayed with the attacker. Renegade's post put the return at about $190K and said all affected users would be made whole.
The attacker added a few words of their own. According to Cointelegraph, they admitted the act wasn't ethical, said they believed returning the funds was the best way to protect users, and called the vulnerability too simple and bad. Blockscout now shows the proxy pointing to an implementation named DarkpoolFrozen.
Why Setup Code Deserves the Same Scrutiny as Trading Code
Most security effort on a protocol like Renegade goes into the parts users touch, the matching, the settlement and the balance accounting. Initializers and migrations get less attention because they're expected to run once, at a moment the team controls. Renegade's account points at exactly that assumption, since the faulty migration shipped in April 2025 and the pool kept trading for about a year before anyone used the opening. Ordinary trading never touches an initializer, so the gap had no way to show up in normal use.
The same pattern turns up wherever setup logic lives on after launch. The lesson for builders is that a migration is a deployment, and every deployment needs a test asking whether a stranger can still call setup afterward.
How Olympix Would Have Shut the Open Initializer
Olympix models a contract as states, transitions and entry points, and for an upgradeable proxy the state at the top of the list is who owns it and which implementation it delegates to. Every entry point that can write either of those values is a path the engine maps. Olympix's static analysis would have surfaced the signal here: a setup function on a live proxy that assigns ownership with no check that it had already run and no restriction on who could call it, sitting next to a storage layout that had been migrated.
That signal narrows the search from every path in the contract, to the feasible ones, to the few that touch the invariant a dark pool lives by. Only the proxy's legitimate owner should ever be able to change its owner or the logic it delegates to, and no one but a depositor should be able to move a depositor's balance. BugPoCer would have run Counterexample-Guided Invariant Refutation from the deployed system outward, starting from the post-migration state, and tried to break that rule from an address with no special role.
The counterexample it would have returned is short. A fresh address calls the initializer, becomes the owner, points the proxy at logic it controls, and transfers the pool's tokens out. BugPoCer would have handed that back with the minimal conditions that trigger it and a generated Forge test that replays it, which is the May 10 drain produced in development instead of on Arbitrum. Because Olympix runs at every merge and before release, the finding would have appeared on the April 2025 migration itself, the change Renegade says opened the door.
A Bounty Paid for a Setup Step
The person who found Renegade's gap gave most of the money back, and Renegade still paid 20,000 USDC and paused a deployment because one setup function stayed callable after a migration. The rule that function broke is the simplest one a proxy has, which makes it the kind of rule an engine can infer and test on every change. To see how Olympix checks the initializers and upgrade paths in your own contracts and returns a runnable counterexample when one is left open, book a technical walkthrough.
On-Chain References
Protocol: Renegade V1 Arbitrum dark pool
Chain: Arbitrum
Date: May 10, 2026, 08:27:23 UTC
Loss: about $209K drained (about $190K returned, 20,000 USDC kept as a bounty)
Attacker wallet: 0x7772...7777
Contract named as new proxy owner: 0x33FB...4a34
Dark pool proxy: 0x30bD...C518
Renegade return wallet: 0xE4A7...CFBE
Exploit tx: 0x0e49...c77e
Block: 461301926
Renegade on-chain message tx: 0x9c3e...6121
First return tx (WBTC): 0xfc4d...629d
USDC return tx (84,383.59 USDC): 0x4551...2cd0
More post-mortems
See every post-mortem →See what Olympix finds on your own code
Send us a repo that's already been audited, and we'll run Olympix at the same commit and show you what comes back.




