NullMeridian Inquire

NullMeridian

We look where the light bends.

A whitehat security practice. Protocols and smart contracts first. Scope first, proofs you can run.

Request a scopeWhat we review

01 · Primary

Smart-contract and protocol security.

Bounded reviews. The scope is written down and the limits are stated up front. Every review is scoped to a fixed commit, and you keep the invariant harness.

  1. 01

    Line-by-line manual review

    Every in-scope line, read against the threat model.

  2. 02

    Stateful invariant fuzzing

    What must never break, tested across call sequences.

  3. 03

    Foundry PoCs

    A runnable proof for every High and Critical finding.

  4. 04

    Fix review

    The last step of every engagement. Fixes are re-checked.

Formal or symbolic methods where justified. Rates quoted after scoping.

Request a scope

02 · Also

Other capabilities.

Protocols and smart contracts come first. We also take this work, scoped the same way.

Authorization

No live system is tested without written authorization from someone who can give it. You confirm that on the intake form, and sign it before any testing.

Live-system work

Live-system testing begins only after the client signs a written Testing Authorization and Rules of Engagement that lists every in-scope host, URL, IP range, API, and cloud account, confirms the client owns or controls them (or holds the owner's written permission), and names a testing window and emergency contact. Nothing outside that list is tested.

Authorization is given by a person with authority to bind the client and the right to authorize testing of the in-scope systems, who warrants both in the Rules of Engagement. Where a third party hosts or operates an in-scope system, the client is responsible for that party's required permissions.

We prefer a staging environment that mirrors production. Production testing happens only where you name the targets in writing and only within agreed limits: no denial-of-service or destructive tests without separate written approval, no bulk data exfiltration (we capture the minimum to prove a finding), no social engineering or physical testing unless separately authorized, and an immediate stop-and-notify if anything looks unstable or already compromised.

03 · Method

Threat model first.

Then the reading. Then the proofs.

  1. 01

    Threat model first

    Assets, actors and trust assumptions are written down before the review starts.

  2. 02

    Manual review

    Line by line. Supported by tools.

  3. 03

    Fuzzing and invariants

    Stateful invariant fuzzing for what the system must never violate.

  4. 04

    PoCs

    Foundry PoCs for High and Critical findings.

  5. 05

    Formal or symbolic methods

    Where justified.

  6. 06

    Tools support the reading

    They don't replace it.

Deliverables

  • Findings, each with its severity rationale.
  • Runnable PoCs for High and Critical findings.
  • For smart contracts: an invariant harness that you keep.
  • The residual risk, stated.

04 · Process

Five steps, in order.

A fixed scope and version from the start.

  1. 01

    Intake

    You send the request. We read it.

  2. 02

    Scoping and threat model

    A fixed scope and version, and a written threat model. For live-system work, written authorization comes first.

  3. 03

    Review

    Critical findings are disclosed early. Not held for the report.

  4. 04

    Draft report and walkthrough

    We go through each finding with your team.

  5. 05

    Fix review

    Fixes are re-checked at the fix commit.

Limits

  • Time-boxed.
  • Fixed scope and version.
  • Anything out of scope is excluded.
  • Live-system work needs written authorization. See the terms.
  • Key management, custody, and operational security are out of scope unless named in the signed scope.
  • A mutual NDA is available on request, signed before any scope detail is shared.

05 · Sample

A glimpse of a finding.

Synthetic sample, fictional contract. It shows how a finding is written.

Synthetic sample. Fictional contract. This report is synthetic and invented to show our format. The contract, commit, finding and code below are fictional. It is not from a real engagement and describes no real client, protocol or vulnerability.

NM-SAMPLE-01 · Share calculation rounds in the caller’s favour on withdraw

  • SeverityMedium (illustrative)
  • ImpactMedium: small, repeatable loss to remaining depositors
  • LikelihoodMedium: anyone can trigger it; profitable only where gas is cheap
  • LocationExampleVault.sol, withdraw() (fictional)
  • StatusFixed in 1111111 (placeholder)
Read the full finding

Description

In withdraw(assets), the vault computes the shares to burn with rounding down (it should round up, per ERC-4626 previewWithdraw). The caller burns slightly fewer shares than the assets they receive are worth, so each call moves a small amount of value from other depositors to the caller.

Severity reasoning

Impact: each call leaks at most one unit of rounding, so total loss is bounded by call count and gas cost, which keeps impact at Medium. Likelihood: anyone can trigger it with no preconditions, but it pays only where gas is cheap relative to the unit, so Medium.

Proof of concept (Foundry, fictional)

function test_withdrawRoundsInCallerFavour() public {
    vault.deposit(1_000e18, bob);
    vault.deposit(1_000e18, alice);
    asset.transfer(address(vault), 1e18); // simulated yield: share price above 1, so withdraw(1) burns 0 shares
    uint256 before = vault.convertToAssets(vault.balanceOf(bob));
    for (uint256 i; i < 100; ++i) vault.withdraw(1, alice, alice);
    assertLt(vault.convertToAssets(vault.balanceOf(bob)), before);
}

Recommendation

Round up when converting assets to shares on withdraw (round against the caller), and add an invariant that total assets cover total shares.

Fix review

Verified at the fix commit: rounding now favours the vault and the new invariant holds under stateful fuzzing.

Report context

  • ClientExample Labs (fictional)
  • Repositoryexample-labs/example-vault (fictional)
  • Commit0000000000000000000000000000000000000000 (placeholder)
  • In scopesrc/ExampleVault.sol (fictional)
  • MethodManual review, invariant testing with Foundry, triaged static analysis
  • Findings1 shown here, for format only

The review covers only the files listed above at the listed commit. Code outside scope, later changes, deployment, key management and off-chain components are not covered. A review reduces risk; it does not certify that code is free of vulnerabilities.

Assets: deposited assets and vault shares. Actors: depositors, a privileged owner, any external caller. Assumption: the owner key is not compromised.

Real reports state the actual repository, commit hash and files in scope, and are delivered only to the client. Publication is the client’s decision.

06 · Intake

Request a scope.

Tell us what to read. Rates quoted after scoping.

Active incident?

Don't use this form. Email ops@nullmeridian.space with the subject ACTIVE INCIDENT.

Don't send private keys, passwords, credentials, or details of an unpatched vulnerability. We'll arrange a secure channel.

For smart contracts / protocol

A URL, or "private / we'll arrange access". Don't send access credentials here.

The exact commit hash. We review the commit you name, not a moving branch.

Target chain(s) and network, plus the compiler or language version if known.

For blockchain infrastructure, web or API application, cloud or infrastructure, other

Authorization is given by a person with authority to bind the client and the right to authorize testing of the in-scope systems, who warrants both in the Rules of Engagement. Where a third party hosts or operates an in-scope system, the client is responsible for that party's required permissions.

Live-system testing begins only after the client signs a written Testing Authorization and Rules of Engagement that lists every in-scope host, URL, IP range, API, and cloud account, confirms the client owns or controls them (or holds the owner's written permission), and names a testing window and emergency contact. Nothing outside that list is tested.

Blackout periods, rate limits, no-go areas.

What is in scope, and what is explicitly out.

When you need the report.

Why that date. Hard or flexible?

In your words, the failure you most fear. For example: funds drained, data exposed, an admin account taken over, an upgrade that bricks the system. One paragraph is enough.

Email or a private Discord ticket.

The button opens your mail app with the details filled in. Nothing is sent until you send it.

07 · About

A whitehat security firm.

Protocols and smart contracts first. Also web, API and infrastructure work.

How we work with clients

  • The scope is written down first.
  • The limits are stated up front.
  • Every serious finding comes with a proof you can run.

Record

Engagements
No public engagements yet.
Rates
Rates quoted after scoping.

Disclosure

Found something in a system of ours? Read the disclosure policy and security.txt. Privacy terms are on the privacy page.

Products