Security
What holds value
- The pools' ETH and tokens, in positions nobody can remove. A side's ETH only leaves its pool when that side is sold into it: by a trader, or by the hook's realignment after a trade moved the three prices apart.
- The pots, the creator fees and the protocol fees, held by the hook as ETH claims in the Uniswap V4 PoolManager, accounted for each duel apart.
What protects it
- Locked liquidity. Only the factory can open registered pools or add their launch liquidity; withdrawal and donation revert.
- Bounded recipients. A pot only buys its duel’s winner; creator fees only go to the duel’s creator, the launching wallet or an address it handed its role to, which accepted it. Protocol fees go to the current treasury, which the factory owner can change after 48 hours, including for already accumulated protocol fees.
- Bounded factory powers. Tokens have no owner or mint function, and the hook cannot be upgraded or paused. The factory owner can pause new launches, propose bounded terms for future duels, or change the treasury after the delay. It can also lower the protocol's share of every duel's swap fee at once, down to nothing, or raise it back, never above the duel's terms: what the protocol does not take goes to the pots. The owner can give the role up for good (
renounceOwnership): the terms, the treasury, the protocol's rate and a pause then stay as they are, except a change already proposed, which anyone can still apply after its delay. - Settlement before the swap. The first swap after a close settles the finished average before trading. A buyback’s ceiling is about 10% above a reference held with fractional-tick precision: a 30-minute exponential average of the ETH pool's ticks, floored at the current tick so that it follows the price down at once.
- ETH-only rounds. The split and round average use the two ETH pools. An A/B switch that moves no ETH price changes neither the signal nor an otherwise quiet round’s activity.
- Fees on full fills. Swaps charged in advance revert if they cannot fill the requested amount completely. Network gas is separate.
- Isolated realignment. Only profitable loops are kept, capped by the selling pool’s ETH. A failed attempt rolls back and is skipped; one that ran out of gas reverts the swap (
ArbitrageStarved), so a caller cannot skip it by holding gas back. This does not guarantee price agreement or protection from all trading losses. - Same rules across routes. The hook takes fees, taxes and burns whether the router is Duel’s or another V4 router.
The factory starts paused. While paused() is true, only owner() can launch a duel; other callers revert with CreationPaused. The owner opens launches with setPaused(false). Existing duels keep trading.
What the site shows
- Pictures from the site alone. The pages show a duel's pictures from Duel's own address only, and only images the site processed: a JPEG, PNG or WebP read from its header first (1536 × 1536 pixels and 5 MB at most), decoded in WebAssembly, fitted within 1024 pixels and encoded again as WebP, without its metadata. The pages' security policy lets them load images from nowhere else.
- Codecs kept apart. The images are decoded in a Worker of their own, which only the site reaches and which holds nothing: no key, no store. A flaw in a codec would reach only the image it reads. The site checks what that Worker answers (a still WebP of the expected size) before keeping it, and the C decoders start afresh for each image.
- Duels launched from the contract. Their details can name any address. The site shows no https picture; it fetches an IPFS picture once, from a public gateway (5 MB and 10 seconds at most), processes it as an upload and shows its own copy, or the side's initials.
- Uploads within bounds. The site takes pictures from its own pages only: ten a minute from one address, and a limited number a day. A picture no duel names is removed after a day.
How it was checked
- Automated tests cover contract behavior, the web app and alerts bot. Coverage is a test metric, not proof that every possible behavior is safe.
- Fork tests exercise integration with Robinhood Chain’s deployed Uniswap V4 contracts, including the Universal Router, Permit2 and V4 Quoter.
- Regression tests retain cases found during the internal review, including fee accounting, launch edge cases, settlement and depleted pools.
- Invariant tests check accounting across randomized trade, settlement and claim sequences: ETH claims must match amounts owed, and intermediate tokens must not be left in the hook, factory or router. Passing the configured runs does not establish safety for every possible sequence.
The internal review found and fixed an exact-output route around the anti-snipe tax, a split that did not follow a side bought alone, sold-out pools misread by the buyback's reference price, and unsafe links in a duel's metadata.
Reporting a vulnerability
If you think you have found a vulnerability, thank you for taking the time to report it. Please write to us privately on Telegram, at @chatwithdivine, with what you found and, if you can, how to reproduce it, and give us time to look into it before sharing anything publicly. We will answer quickly and keep you informed.
We never write first: only trust @chatwithdivine.