The detection library.
One entry per exploit class. What broke, the protocol mechanic behind it, the invariant that would have caught it stated in plain language, and how to implement it. Where an entry has been backtested against the real transactions, the result is published with it.
12 entries
Reentrancy
The contract sends value before it updates its own books, so the receiver calls straight back in and withdraws against a balance that has not moved yet.
Broken access control
A function that changes ownership, parameters or balances is reachable by anyone because the modifier was never applied.
Integer overflow and underflow
Arithmetic wraps instead of reverting, so a balance of zero minus one becomes an enormous number and the guard that was meant to catch it is always true.
Unchecked call return value
A transfer fails and returns false rather than reverting. Nothing checks it, so the books are debited for value that never moved.
tx.origin authentication
Authorisation checks who signed the transaction rather than who called the function, so any contract the owner touches can act with their authority.
Unsafe delegatecall
Foreign code runs against your storage layout. A write the logic contract thinks lands in its own slot 0 overwrites the proxy implementation address.
Oracle price manipulation
A price taken from instantaneous pool reserves is moved with a flash loan, borrowed against at the wrong valuation, then restored in the same transaction.
Front-running and MEV
Pending transactions are public. An attacker reads the intent, pays more gas to land first, and extracts the difference.
Signature replay
A valid signature is accepted more than once because nothing consumes a nonce or checks an expiry, so the same authorisation pays out repeatedly.
Uninitialised proxy implementation
The logic contract behind a proxy was never initialised, so anyone can call initialize on it directly and take ownership of the implementation.
Block timestamp manipulation
An outcome depends on the block timestamp, which the proposer can nudge by several seconds and simulate in advance until it favours them.
Denial of service via gas limit
A loop iterates an array anyone can grow. Enough entries, or one reverting recipient, and the function can never complete again.
On the backtest column. An entry marked backtested means the invariant was run against the real chain data around the exploit, and the result — when it fired, how far ahead, and how noisy it was in a clean control period — is published on the entry. Entries without it carry the reasoning but not yet the evidence, and are labelled that way rather than quietly implying both.
These are the invariants we would write for you.
The library is the reasoning in public. If you would rather have it applied to your own contracts, send an address and we will do five of them for free.
Why publish it at all
Because the invariant is the product, and an invariant you can read is the only honest way to judge whether we know the mechanics well enough to be useful on your protocol.
Every entry here is one somebody can disagree with in public. That is the point.