FIRN

Executed executed

Security

A Core is a vault holding one asset. It is not deployed — and every build compiles it, runs 15 properties against it on a real EVM, then compiles five broken copies and requires the suite to catch every one.

Four claims

The four sentences this category prints

They are on every front page in this business, including the one this site is a rebrand of. Each is a design decision here, and each has a property that executes it.

No inflation attack

The first depositor cannot be front-run into a rounded-down zero. A virtual offset of 1e6 is added to supply and assets in every conversion, so the attacker pays for the rounding rather than the victim.

Donations do not reprice

Assets are tracked in a counter that only deposit, redeem and Accumulation move. A transfer straight to the Core changes its balance and changes nothing a holder can see.

The fee is capped in code

The protocol cut is an immutable constant, not an owner setting. There is no function that raises it and no proxy to replace it with one, which is a different sentence from "we have not raised it".

The owner cannot take principal

No function reachable by the owner reduces a holder's claim. Checked by walking the ABI rather than a hand-written list of functions, because a hand-written list tests the list.

The method needs no toolchain and no testnet. An eth_call may carry a state override — a map of address to code applied before the call and discarded after — so the compiled test contract is placed at a scratch address and a public Ethereum node executes the whole suite for free.

The suite

What ran

PropertyResult
P1the first deposit mints at the offset price and converts back to what went inheld
P2rounding never favours the holder at any size: assets(shares(x)) <= xheld
P3a donation straight to the Core does not move the price of a Laminaheld
P4the inflation attack is unprofitable: the victim keeps 99.9% after a 10,000x donationheld
P5ablation pays exactly what previewAblate quoted, to the weiheld
P6totalAssets tracks flows rather than the token balanceheld
P7a fee above the cap in code revertsheld
P8a fee at the cap is acceptedheld
P9a stranger cannot set the feeheld
P10Accumulation raises the price and accrues exactly the fee that is setheld
P11accrued fee income is outside every holder's claimheld
P12Stagnation stops deposits and Accumulation and does NOT stop ablationheld
P13no owner-only function reaches the principal: after calling every one, the depositor still redeems in fullheld
P14the journey in order — deposit, deposit, Accumulate, ablate — leaves the depositor ahead and the Core solventheld
P15the external surface is exactly the 26 functions written downheld
Executed with solc 0.8.26, optimizer 200 runs through an eth_call state override at 0x00000000000000000000000000000000000f19c0. Re-run on every build.

Breaking it

And what happened when it was broken

A suite that passes is evidence of nothing until you have watched it bite. five defects, one per copy, each of which must be caught. A sabotage that gets through is a hole in the suite and fails the build.

Defect introducedCaught byExpectation
S1the Core prices itself off its token balance instead of its counterP3, P4, P10, P11, P14must be caught
S2setFee stops checking the capP7must be caught
S3Stagnation also halts ablation, trapping holdersP12, P13must be caught
S4ablation burns the shares before it prices them, so the quote driftsP5, P12, P13, P14must be caught
S5an owner-only rescue() is added that moves the whole balanceP15must be caught
S6the virtual offset is removed and the textbook conversions used insteadnot caughtexpected to pass
not caught, and correctly so: tracked accounting already blocks the attack the offset defends against, so removing it changes no property. This is why the Core does not claim the offset is what protects the first depositor.
Each row is a separate compilation of Core.sol with one change, run through the identical suite.

Two of these are worth reading in full. The added rescue() was caught by the ABI-surface check and by nothing else — the property that says no owner function reaches the principal calls a list of owner functions written by hand, so it was testing the list. And the last entry is expected not to be caught, which is a result about the contract rather than an oversight: this Core's tracked accounting already blocks the attack the virtual offset defends against, so removing the offset changes no property. Two defences, one hole. That is why nothing here claims the offset is what protects the first depositor.

Not an audit. 15 properties and a mechanical surface check are a much weaker claim than a review by people who do this for a living, and a much stronger one than a paragraph. Nothing is deployed.