SAFETY LAMP · BRASS, GLASS, GAUZE
The lampLit, and nothing is deployed

Audit

Ten rules, the test that proves each, and what is still not proven.


86 tests, 0 failed, 0 skipped — 62 local and 24 against a BSC mainnet fork with both RPC variables set. Twenty-six guards were deleted from the source on purpose and the tests that claim to catch them were required to fail.

Status

Nothing is deployed. No address exists on any chain.

There is no factory address, no vault address and no mine address, on mainnet or on any testnet. No transaction has been broadcast. What exists is source, a test suite, the measurements on these pages — and a deploy script that has not been run.

01  /  The ten rules
86Tests passed · 0 failed · 0 skipped
24of 86Against a BSC mainnet fork
26of 26Guards proven red in the recorded run
3Stateful invariants · 256 runs each
108,115gasreceive(), against a 1,000,000 ceiling
Fig. 08 — the ten rules as a matrix11 rows · 1 open item
RULEWHAT THE ROW COVERSVERDICTNAMED TESTS001Base, UI schema, Guardian, no DoSPASS3001Commission recommendationOPEN ITEM1002Factory and commission mechanicsPASS2003Fairness, no privileged sandwichPASS2004Literal, UI-friendly, bilingual errorsPASS2005receive() gasPASS1006Integration testsPASSthe suite table007AI OracleN/Anone named008Trigger ServiceN/A1009Emergency controlsN/A2010VaultBaseV3 / ERC-20 quote accountingN/A16 PASS · 1 OPEN ITEM · 4 NOT APPLICABLE BY THE RULE’S OWN TERMS15 NAMED TESTS ACROSS 11 ROWSRULEVERDICTNAMED TESTS001PASS3001OPEN ITEM1002PASS2003PASS2004PASS2005PASS1006PASSthe suite table007N/Anone named008N/A1009N/A2010N/A16 PASS · 1 OPEN · 4 N/A15 NAMED TESTS ACROSS 11 ROWS

Two rows carry rule 001, because the rule has two parts and one of them is the open item. The tick count on each row is the number of tests named in that row’s Proof column — it is a count of evidence, not a score. Rule 006 is proved by the suite table rather than by named tests, and rule 007 has nothing to name because nothing calls the interface.

001Pass · one open item

Base, UI schema, Guardian, no DoS

Inherits the Flap v2.2 vault and factory bases unmodified. The published schema describes eight real methods with correct ABI types and write flags; the only privileged function in the system is setProject, which is Guardian-only, and nothing can revoke the Guardian. Settlement never loops over participants.

Prooftest_setProject_is_guardian_only_and_the_emergency_pair_is_absenttest_schema_lists_every_user_facing_methodtest_a_ten_week_gap_does_not_make_a_period_unsettleable
001Needs Flap’s decision

Commission recommendation

The rule recommends msg.value * 6 / taxRateBps — 3% at a 2% tax. This vault credits 30% to a launcher-configured project address snapshotted per period: ten times that. Not a hardcoded developer address, and flagged rather than decided.

Prooftest_project_is_snapshotted_when_epoch_funding_begins
002Pass

Factory and commission mechanics

Factory spec v2.2. newVault reverts unless the caller is Flap’s VaultPortal, and payload length and address padding are checked before decoding. Native BNB only. The commission figures are measured on the real chain: 9,000 bps kept with no receiver, 8,700 with one, and that 300 bps is a cut of the wage bill.

Prooftest_only_the_vault_portal_can_create_a_vaulttest_vaultDataSchema_matches_the_decoded_abi
003Pass · with disclosures

Fairness, no privileged sandwich

Tax arriving in period N funds N+1, and credit follows the period owning the seed block rather than the submission. Project, referrer and rounding remainder all resolve from a funding-time snapshot, and no admin can rewrite the split. Disclosed rather than hidden: multi-address Sybil, and a block producer’s influence over one seed block.

Prooftest_each_epoch_only_receives_its_own_precommitted_buckettest_RED_project_change_cannot_redirect_a_funded_epoch
004Pass

Literal, UI-friendly, bilingual errors

Every require in our own code carries a literal English-and-Chinese string, and we declare no custom errors. The vendored Flap prelude keeps its own — we did not fork the base.

Prooftest_RED_malformed_vault_data_revertstest_RED_every_launch_bound_rejects_out_of_range
005Pass

receive() gas

Period arithmetic on its own copied values, one bucket write, a project snapshot, two counters and one event. No loop, no external call, no transfer, no delegatecall. 108,115 gas measured inside a real TaxProcessor dispatch on a BSC mainnet fork, against Flap’s 1,000,000 ceiling — see Fig. 11.

Prooftest_receive_gas_under_a_real_taxprocessor_dispatch
006Pass

Integration tests

86 tests, 0 failed, 0 skipped, of which 24 fork BSC mainnet, register the factory on the real VaultPortal, launch a real taxed token, buy on the bonding curve and dispatch real tax. Plus three stateful invariants. Nothing on the fork path is mocked.

Proofnine suites — Fig. 09
007Not applicable

AI Oracle

Nothing in either contract calls Flap’s AI provider interface.

Proofnothing to prove
008Not applicable

Trigger Service

No trigger request and no callback. Settlement is a permissionless public call that pays its caller 2%, which is why it does not need one.

Prooftest_a_period_nobody_mined_sweeps_to_the_project
009N/A by the rule’s own exception

Emergency controls

Both contracts are BeaconProxies. Rule 009 says such a vault is fully exempt and must omit the emergency functions entirely — neither carries any of the five. The beacon moves ownership to the Guardian inside its constructor.

Prooftest_RED_beacon_owner_is_the_guardian_not_the_deployertest_RED_unsupported_chain_reverts
010Not applicable

VaultBaseV3 / ERC-20 quote accounting

A native-BNB VaultBaseV2 with no vaultQuoteToken(). The tax token being a V3 token does not imply a V3 vault base.

Prooftest_RED_non_native_quote_is_rejected
Key11 rows

What the edge mark means

6Pass. The rule applies and a test in this repository stands behind each claim.
1Open. The 30% project share is ten times what rule 001 recommends; Flap decides, not us.
4Not applicable by the rule’s own terms — no AI oracle, no trigger service, a proxy vault under the emergency exemption, and no ERC-20 quote token.
Total15 named tests86 in the run
02  /  Build

The compiler settings are part of the result.


Solidity 0.8.26, EVM version cancun, optimizer 200, IR pipeline on — all pinned. Leaving the EVM version unpinned lets a newer toolchain retarget the bytecode to a fork BNB Chain does not run.

The vault is the tight one: 1,424 bytes of headroom under the 24,576-byte contract size limit.

Solidity0.8.26
evm_versioncancun, pinned
Optimizer runs200
via_irtrue
Why pinnedan unpinned version retargets the bytecode
Contract size limit24,576 bytes
Tightest contractCoalVault, 1,424 bytes spare
Fig. 12 — EIP-170 headroomone track is the whole limit
RUNTIME BYTES AGAINST EIP-170’S 24,576-BYTE LIMIT — EVERY TRACK IS THE WHOLE LIMITCoalVault23,1521,424 SPARECoalVaultFactory8,23316,343 SPARECoalMine8,13216,444 SPARECoalMineDeployer2,20422,372 SPARECoalVaultDeployer2,19722,379 SPARECoalBeacon79823,778 SPARECOALVAULT IS THE TIGHT ONE — 1,424 BYTES SPARE, 5.8% OF THE LIMIT.THE FACTORY HOLDS TWO CREATION-CODE DEPLOYERS RATHER THAN BOTH CONTRACTS, BECAUSE CARRYING BOTH WOULD EXCEED IT.RUNTIME BYTES — FULL TRACK IS EIP-170’S 24,576CoalVault23,152 B · 1,424 SPARECoalVaultFactory8,233 B · 16,343 SPARECoalMine8,132 B · 16,444 SPARECoalMineDeployer2,204 B · 22,372 SPARECoalVaultDeployer2,197 B · 22,379 SPARECoalBeacon798 B · 23,778 SPARECOALVAULT: 1,424 BYTES SPARE,5.8% OF THE LIMIT.

From forge build --sizes with the pinned settings — Solidity 0.8.26, evm_version = "cancun", optimizer 200, via_ir = true. Leaving the EVM version unpinned lets a newer toolchain retarget the bytecode to a fork BNB Chain does not run, which would change every bar here.