ShapeShift FOX Colony's $137K Loss and How Olympix Would Have Prevented It
At 15:45:50 UTC on May 13, 2026, one transaction on Arbitrum emptied the treasury of FOX Colony, the community governance program ShapeShift DAO runs for FOX token holders. The colony's contract sent 132,704.59 USDC straight to the attacker's wallet and 841,086.34 FOX to a contract the attacker had deployed seconds earlier, which sold the FOX on Uniswap V2 for 1.95 WETH. Together that comes to about $137,000, the figure Our Crypto Talk reported from the on-chain data. Blockaid flagged the drain about 18 minutes later.
The attacker never touched an admin key or a price feed. According to the security firms that traced it, the drain began with a meta-transaction the attacker signed with their own key, which the colony's contract then carried out against itself.
A Colony Built on a Router
FOX Colony runs on Colony Network, a framework for organizations that manage shared funds and permissions on-chain. Colony contracts use a routing pattern called EtherRouter. The router holds the colony's storage and funds, and for every call it asks a separate resolver contract which implementation holds the code for that function, then delegatecalls into it. Swapping the resolver changes what code the router runs, which is how the system upgrades, and it's also why the function that sets the resolver is the most sensitive switch in the whole contract.
That switch, setResolver, is protected by DSAuth, a long-standing authorization library. Its auth modifier lets a call through only if the caller is the owner, is allowed by the configured authority, or is the contract itself. That last rule exists so a contract can call its own protected functions as part of normal internal work.
The colony also exposed executeMetaTransaction, a convenience feature that lets a user sign an action off-chain and have someone else submit it and pay the gas. To carry out the signed action, the contract calls itself with the requested function.
Two Trust Rules That Met in the Middle
SlowMist's analysis of the victim contract, 0x5c59...52da, traces the drain to the way those two pieces combined. The meta-transaction feature let a signed request make the contract call itself with any function, and it had no list of sensitive functions it refused to forward. DSAuth, meanwhile, treats any call coming from the contract itself as authorized. So when a meta-transaction asked for setResolver, the router saw the call arrive from its own address, and DSAuth waved it through before it ever checked whether the original signer was the owner or held any role.
SlowMist's write-up shows setResolver guarded by the auth modifier alone, so once DSAuth accepted the self-call, nothing else stood between a stranger's signed request and the resolver. Blockaid summed it up the same way in its alert, saying the router auto-trusts any call where the sender is the contract itself.
How the Treasury Left in One Transaction
SlowMist describes the sequence. The attacker used a signed meta-transaction to have the colony call setResolver on itself, pointing the router at a resolver the attacker controlled. From that moment, every function the router looked up resolved to code the attacker chose. The attacker's resolver mapped a drain function to an implementation that transferred the router's ERC-20 balances out, and because the router delegatecalls whatever its resolver returns, that transfer ran with the colony's own balances.
The on-chain record matches. In transaction 0xdda5...207d, Arbiscan shows the 132,704.59 USDC moving from the colony contract to the attacker's wallet, and the 841,086.34 FOX moving to the freshly created contract 0x835a...9f5c, which sold it into the Uniswap V2 WETH/FOX pair for 1.95 WETH. The attacker's wallet had deployed two other contracts in the blocks just before.
Where the Money Went
SlowMist's fund tracing labels the wallet 0xeed2...bf28 as the ShapeShift exploiter. It reports that the wallet's gas came in through Tornado Cash and that most of the value, about $137,000, went out through LI.FI for cross-chain swaps, with a smaller amount routed through Relay.link. Arbiscan shows the wallet approving USDC and WETH and calling LI.FI's Permit2 proxy within minutes of the drain. According to SlowMist, part of the stolen funds later sat in Spark savings and touched Tornado Cash again, which makes tracing harder.
Blockaid's warning went wider than ShapeShift. In its alert, the firm said every Colony Network colony that exposes executeMetaTransaction on top of EtherRouter, on any chain, is exposed to the same primitive. As of the reports Our Crypto Talk and Crypto Times published on May 13 and 14, neither ShapeShift DAO nor Colony Network had issued a public statement, a recovery plan or a fix.
A Conflict Between Two Libraries
SlowMist describes the root cause as a semantic conflict between the router's meta-transaction primitive and the legacy DSAuth library: one turns an outside request into a call from the contract itself, and the other treats a call from the contract itself as fully trusted. Its recommendations follow from that, a denylist of sensitive functions inside executeMetaTransaction and great caution with any rule that authorizes the contract's own address unconditionally. The flaw lived in the path that ran through both pieces at once, where a check on any single function in isolation would find nothing wrong.
How Olympix Would Have Closed the Self-Call Path
Olympix reads a contract as states, transitions and entry points. For an EtherRouter colony, the state that matters most is the resolver address, since it decides which code runs against the treasury. The engine maps every entry point that can write that slot, including indirect ones, and executeMetaTransaction is one of them, because it can forward a call back into the contract.
Olympix's static analysis would have surfaced the signal on that path: an externally reachable function that makes the contract call itself with caller-chosen data, feeding into an auth check that unconditionally trusts the contract's own address. That signal narrows the search from every path in the router, to the feasible ones, to the handful that reach setResolver.
From there BugPoCer would have worked from the system outward with Counterexample-Guided Invariant Refutation. The invariant it would have inferred is simple to state: only the owner or an authorized role can change the resolver, so an address with no role should never be able to make the router run new code. BugPoCer would have tried to break that rule from an ordinary signer, and the meta-transaction self-call would have broken it. The counterexample it would have returned is the May 13 drain in miniature, a signed request from a stranger that ends with the resolver pointing somewhere new, delivered with the minimal conditions that trigger it and a generated Forge test that replays it in development.
Because Olympix runs at every merge and before release, that test would have failed the build the moment meta-transactions and DSAuth's self-call rule shipped together in the same contract.
The Lesson for Router-Based Systems
Convenience features change who the contract thinks is calling. Any feature that lets the contract act on itself on behalf of a user should be tested against every protected function it can reach, with the user's real permissions, not the contract's. For FOX Colony, a single test of whether a role-less signer could move the resolver would have caught a $137K treasury drain before it reached Arbitrum. To see how Olympix tests the authorization paths in your own upgradeable contracts and hands back a runnable counterexample when one is open, book a technical walkthrough.
On-Chain References
Exploit tx: 0xdda5...207d
Attacker wallet: 0xeed2...bf28
FOX Colony contract (EtherRouterCreate3): 0x5c59...52da
Malicious resolver: 0x4e32...ee0a
Drain implementation: 0x0b97...39e2
FOX swap contract: 0x835a...9f5c
Block: 462441493
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.




