Quorum

Ten readings.
One finding.

A single detector that reports everything it sees is noise. Ten of them are ten times the noise. Quorum pairs its lenses by risk, two readings each for three of them and four for the access risk, and every lens reasons from different evidence.

quorum run

Agreement is signal.
$ quorum run --targets fixtures/VulnerableVault.sol fixtures/OpenFeeSetter.sol
  QUORUM    VulnerableVault.sol:withdraw   reentrancy   corroborated by callorder-lens, guard-lens
  QUORUM    OpenFeeSetter.sol:setFeeRate   unguarded-state-write   corroborated by modifier-lens, sender-lens
scanned 20 lens-units | confirmed 2 | recalled 1 | candidates 5

What a lens may not do

No lens can publish a finding on its own. A lens records what it saw and reads nothing about what its peers saw; the tally of who agreed lives on the finding in memory, not inside any agent. A second lens that reaches the same (contract, function, risk) from a different reading is what turns a sighting into a finding.

The lenses are deliberately simple. They are regex-and-brace-matching heuristics over source text, not a compiler front end. The point of this project is the coordination and memory layer; the lenses are the honest minimum needed to have something real to coordinate about.

callorder-lens

reentrancy

An external call precedes a state write in the same function.

Evidence
call ordering

guard-lens

reentrancy

The function moves value out and carries no reentrancy guard.

Evidence
guard absence

On audited production code

Run Quorum against audited production contracts and it mostly holds its tongue. On Aerodrome’s Router, WETH9 and a Compound proxy it confirms nothing and files twenty candidates. That is the intended behaviour, not a failure to find bugs.

Disagreement is kept as a candidate and never published.

modifier-lens

unguarded-state-write

Externally callable, writes storage, carries no modifier at all.

Evidence
declaration

sender-lens

unguarded-state-write

Writes a privileged-looking variable with no msg.sender check anywhere on the path.

Evidence
reachability

Not a vulnerability scanner that proves exploits

Quorum publishes corroborated idioms worth review, not confirmed vulnerabilities. A quorum means two independent lenses agreed on a shape, nothing more. The Friend.tech recall on the front page is a pattern match on a call idiom, not an allegation about that contract.

The fixtures in fixtures/ are vulnerable on purpose and are not deployed anywhere.

consistency-lens

unguarded-state-write

Writes state that the contract's other writers of it only write behind a guard, and carries no guard at all.

Evidence
the contract's own intent

Why the access risk has four

The first two readings of this risk both key on how a function is written: whether it carries a modifier, and whether the variable it writes carries a privileged-looking name. Modern code writes last_gauge and _validatorsMap, so on recent audit findings the pair corroborated nothing at all. The third reading asks the contract instead: every other function that writes this variable carries a guard, and this one carries none. The fourth came from real 2026 hacks: a function anyone can call hands the caller’s own bytes to another contract, as itself. Two access bugs had been published as reentrancy because nothing else agreed with modifier-lens.

The third was built against bench/MODERN.md and the fourth against bench/HACKS-RECALL.md, and both files say so: neither recall there is a measurement on unseen code.

wrap-lens

unsafe-math

The compiler lets this storage arithmetic wrap: a pre-0.8 pragma, or an unchecked block.

Evidence
compiler context

bound-lens

unsafe-math

Nothing in the function bounds the operands before the write.

Evidence
guard absence

Where the count lives

Corroboration is accumulated across lenses, processes and sessions on the finding entity in the WARM tier. A lens has no idea who else agreed with it; memory does.

The memory

ledger-lens

accounting-mismatch

This balance has no way down anywhere in the contract, and this function relies on it.

Evidence
contract-wide

payout-lens

accounting-mismatch

Value leaves this function against a balance it reads and never reduces.

Evidence
outflow

What the accounting pair cannot see

It sees a balance that only ever grows while value goes out against it: a contract that adds to a balance in one function and never takes it back in another. It cannot see a sibling function that forgot one debit another function has, because there the balance does go down, on the other path. That shape needs a reader that follows calls.

Measured before it was posted: bench/ACCOUNTING.md.

PreviousFront pageNextThe memory