SEXTANT

The contract

Arc

An arc is the graduated sixth of a circle the instrument is named after: the part that holds the reading. An Arc holds one tokenised equity and mints Verniers against it — and it has two exits, because only one of them needs a price.

20

properties, executed. 20 held on the last build.

14

state-changing functions in the compiled ABI, checked against a written-down surface.

nine

sabotages that must be caught. One more is expected not to be, and says why.

1

of them caught by nothing in Solidity — only by reading the compiled ABI.

The design

Only one of the two exits needs a price

fixInKind

Pays your share of what the Arc holds, pro rata. No price appears in it at all — a ratio of two integers the contract already knows.

P9 executes this: the pool is moved up, down and back across four Sights, and the payout for the same shares must be identical to the wei each time.

fixToStable

Pays in USDG, which means the Arc buys your equity from you. That needs a number, and it uses the worse of its last two observations.

P13 executes this: sight either side of a move, in either direction, and the exit never beats the in-kind claim at the lower mark. And it refuses rather than marking its way out.

There is no maxAge anywhere in this contract, and that is a decision rather than an omission. markAge() is public because a caller may want it; nothing here treats it as safety.

Every property, and whether it held on the last build.
propertyheld
P00the first deposit mints, and an in-kind Fix returns exactly what went inok
P01rounding never favours the holder, at every sizeok
P02a stray transfer moves no price until accumulate accounts for itok
P03the inflation attack is unprofitable: the victim keeps 99.9% after a 100x donationok
P04both exits pay exactly what their preview quoted, to the weiok
P05totalAssets tracks the position rather than the token balanceok
P06a Dip above the cap in code reverts, and one at the cap is acceptedok
P07a stranger reaches none of the owner-only functionsok
P08accumulate charges exactly the Dip on the harvest, and no moreok
P09IN KIND NEEDS NO PRICE: move the pool anywhere and the same shares pay the same weiok
P10accrued Dip is outside every holder's claim and survives a full exitok
P11Stow halts Sight, commit, deposit and accumulate — and halts NEITHER exitok
P12the stable exit converts at the WORSE of the last two marksok
P13THE OPTION IS CLOSED: sight either side of a move and the stable exit never beats the in-kind claim at the lower markok
P14a Sight that moves further than the band in one step revertsok
P15a second Sight in the same block reverts, which is what makes the worse-of-two rule mean anythingok
P16transferring a Vernier moves the claim and moves no priceok
P17a zero deposit, either Fix, a commit or a fund all revertok
P18the pool's orientation is read from the pool, both ways round, and a pool of another pair is refusedok
P19the stable exit refuses rather than marking its way out, and the in-kind exit still works in the same blockok

The second half is the point

Break it, and watch the suite bite

A passing test suite is evidence of nothing until you have seen it fail on purpose. Each entry below is a copy of the contract with one deliberate defect, compiled fresh and put through the same properties. A sabotage that passes is a hole in the suite and it fails the build.

defectcaught by
the stable exit quotes the latest mark instead of the worse of the last two
the whole design. Without it a redeemer picks the better of two observations and the difference comes out of everyone who stayed
P12, P13
the in-kind exit is routed through the mark
the exit that needs no price is the one thing on this contract that cannot be wrong. Route it through an observation and it can
P00
the Dip cap is not enforced
a fee capped in prose is not capped
P06
the position is read from the token balance
the classic donation vector, and the reason the accounting is tracked
P05, P08
a second Sight in the same block is allowed
without it an attacker moves the pool, sights twice, and both marks are the price they just made — which empties the worse-of-two rule of all its content
P15
a Sight accepts any size of step
a pool that moves thirty per cent in one block has been traded through, not repriced, and the answer is to stop rather than to quote it
P14
Stow also halts the in-kind exit
an emergency stop that traps holders is the emergency
P11
the pool orientation is assumed rather than read
a vault pointed at a pool the wrong way round does not revert. It quotes a reciprocal, and the only symptom is a price that looks odd to somebody who already knows the answer
P18
an owner-only rescue() is added
caught by NOTHING in Solidity. Every property still holds — none of them says anything about a function that does not exist — and the owner can take the principal. Only a mechanical read of the compiled ABI against a written-down surface sees a function that was added
the ABI surface — rescue(address)
the amount check at the top of deposit is removed
NOT caught, and correctly so: previewDeposit(0) is 0, so the share guard one line below refuses exactly the same calls and P17 still holds. Two guards, one hole. This is why nothing on the site claims the amount check is what makes a zero deposit impossible
nothing

The one worth reading twice is rescue(). Adding it breaks no property — none of them says anything about a function that does not exist — and it hands the owner the principal. A hand-written list of “functions the owner can call” would have tested the list.