Redacted sample report

Cloak contracts: security review

This is a shortened, redacted version of a real Proovant report. One finding is shown in full. The others are listed with their severity and outcome, and their detail is blacked out. Everything shown here is already public in Cloak's own review log or comes from our own test runs.

ProjectCloak (sealed-bid auctions, shielded pool)
Reviewed commit27bffaa
Report date7 November 2026
PlanHuman-reviewed (as Verified)
Findings12, all with passing tests
TestingFoundry, local chain

1. Summary

Twelve findings: nine in the contracts planned for mainnet and three in testnet-only code. Each was reproduced in a Foundry test before it was reported. None lets anyone take bidder deposits or private balances. The most serious allow a bidder or creator to gain an unfair result in a drop or launch, or to block a feature for others.

IDFindingSeverityOutcome
CL-01A bidder with several sealed bids could steer the NFT drop tie lottery by choosing which bids to openMediumFixed
CL-02In an undersubscribed launch, a dust bid at the minimum price sets the price for everyoneMediumBy design
CL-03One well-funded actor can fill a launch's deposit capMediumAccepted
CL-04A creator can inflate their own drop with bids they keep sealedMedium-LowMitigated
CL-05Anyone could open a per-token vault for a Uniswap launch before it was admitted to the shared vault, locking it outLow-MediumFixed
CL-06One very large batch order made the whole round refund, less the vault feeLow-MediumFixed
CL-07A whitelist spot sale's naming deadline could be one second after bidding closedLow-MediumFixed
CL-08The private router refused native currency paid out by a Uniswap v4 marketLowFixed
CL-09A note owner could withdraw as a relayer fee to themselves and skip the withdrawal feeLowFixed
A-1A large donation pushes a launch onto a different market path (testnet-only code)LowDocumented
A-2A collection returning a malformed ownership value could block escrow claims (testnet-only code)Low-MediumFixed
A-3The escrow drop's draw had the same weakness as CL-01 (testnet-only code)With CL-01Fixed

Severity is our rating. Outcomes are as published by the Cloak team: 8 fixed, 1 mitigated, 3 left as they were (by design, accepted, or documented).

2. Scope and method

3. Finding CL-01, in full

A bidder with several sealed bids could steer the tie lottery by choosing which bids to open

SeverityMedium
ComponentCloakDrop (and the escrow drop, as A-3)
OutcomeFixed, and the fix was tested

What happens. When a drop is oversubscribed at the clearing price, a lottery decides which of the tied bids win. The lottery seed was derived only from the salts of the bids that were opened. A bidder who holds several sealed bids therefore controls part of the seed: by choosing which of their own bids to open, they choose between many possible draws.

Who can do it. Any bidder with more than one sealed bid. It needs no special role. The cost is the penalty on each bid left sealed.

Exploit scenario. The bidder places several small sealed bids. After bidding closes they compute, off-chain, the lottery result for every combination of their bids, pick the combination that wins the most, and open only those.

Impact, in numbers from the test. A flat-price drop of 10 NFTs, 30 honest single-NFT bids, and an attacker with 8 sealed single-NFT bids. A fair share for the attacker is about 2.1 NFTs. The best of the 256 combinations wins 7, for a net profit of 13.9 units of the native currency in this setup after penalties.

Proof of concept. Copy the test file into contracts/test/ and run it from contracts/. Nothing in the source is modified.

$ forge test --match-path test/CloakPoc_Drop_CL01_CL03_CL04.t.sol -vv

[PASS] test_poc_tieGrind() (gas: 809676152)
Logs:
  reveal-all NFTs won (one sample draw): 6
  fair expectation x1000 (8 tickets of 38, 10 NFTs): 2105
  best mask: 223
  best NFTs won: 7
  best net profit (wei): 13900000000000000000

Suite result: ok. 3 passed; 0 failed; 0 skipped

Test assumptions. Local chain. A flat-price drop with one price tick. No mocks are needed for this test. The other two tests in the file belong to CL-03 and CL-04.

Recommendation. Add entropy to the draw that no bidder knows while bids can still be opened, for example the hash of a block after settlement.

Fix review. The team changed the draw to also use the hash of the block after settlement. We reran the attack against the fixed code over 60 fresh block hashes. The best-looking combination won 95 NFTs in total, against 128 for opening every bid, where a fair share is about 126. Choosing which bids to open no longer helps.

4. Findings CL-02 to CL-09 and A-1 to A-3

Redacted in this sample

In the full report each finding has the same sections as CL-01: what happens, who can do it, the scenario, the impact in numbers, the test and its command, the assumptions, and a recommendation.

5. PoC package

The report ships with a package of drop-in test files, a short README with one command per finding, and the logs of our own runs. Where a test replaces something with a stand-in, the README says so. In this review the ZK verifier was replaced by the team's own mock verifier in the tests that touch it.

6. Limits of this review

Request a review