source
carlet's fork-choice logic, in full and verbatim.
// carlet / fork-choice
// at the close of a turn, the tine with the highest measure is kept.
// every other tine is cut. nothing here invents a number it cannot read.
type TineId = string;
interface ReserveSplit {
// a mapping from reserve name to weight. weights sum to one.
[reserve: string]: number;
}
interface TineConfig {
feeBps: number; // transfer fee withheld at the protocol level
split: ReserveSplit; // how the withheld fee moves across reserves
floorPull: number; // how hard the floor leans when price slips
depthFeed: number; // how much of the split goes to depth
}
interface Tine {
id: TineId;
config: TineConfig;
bornAtTurn: number;
}
interface TurnReading {
// real readings taken over the turn. never synthesized.
// any field may be absent, in which case the measure cannot be formed.
realizedReserveGrowth: number | null;
depthStability: number | null;
floorHeld: boolean | null;
retention: number | null;
}
interface MeasuredTine {
tine: Tine;
measure: number | null;
}
interface ForkResult {
turn: number;
kept: TineId | null;
cut: { id: TineId; gapToKept: number | null }[];
refused: boolean;
}
// weights are set on chain and read here. they are never hardcoded,
// so an unset weight yields no measure rather than a guessed one.
const WEIGHTS = {
reserveGrowth: null as number | null,
depthStability: null as number | null,
retention: null as number | null,
};
function measureTine(tine: Tine, r: TurnReading): number | null {
// the floor is not optional. a tine that let the floor fall
// cannot be measured at all, whatever else it did.
if (r.floorHeld === false) return null;
// a measure needs every input it weighs.
// a missing input yields no measure, not a zero.
if (
r.realizedReserveGrowth === null ||
r.depthStability === null ||
r.retention === null ||
WEIGHTS.reserveGrowth === null ||
WEIGHTS.depthStability === null ||
WEIGHTS.retention === null
) {
return null;
}
return (
r.realizedReserveGrowth * WEIGHTS.reserveGrowth +
r.depthStability * WEIGHTS.depthStability +
r.retention * WEIGHTS.retention
);
}
function fork(turn: number, tines: Tine[], r: TurnReading): ForkResult {
const scored: MeasuredTine[] = tines.map((t) => ({
tine: t,
measure: measureTine(t, r),
}));
// only a tine with a real measure is eligible to be kept.
const eligible = scored.filter((s) => s.measure !== null);
if (eligible.length === 0) {
// no tine could be measured this turn.
// the previous version keeps governing.
return { turn, kept: null, cut: [], refused: true };
}
// keep the highest measure. ties resolve to the older tine.
eligible.sort((a, b) => {
if (b.measure! !== a.measure!) return b.measure! - a.measure!;
return a.tine.bornAtTurn - b.tine.bornAtTurn;
});
const winner = eligible[0];
// the floor gate runs before the fork is allowed to land. see /article.
if (!floorWouldHold(winner.tine)) {
// the winning tine scored highest and still cannot run.
// file the refusal, hold the previous version.
return { turn, kept: null, cut: [], refused: true };
}
const cut = scored
.filter((s) => s.tine.id !== winner.tine.id)
.map((s) => ({
id: s.tine.id,
gapToKept: s.measure === null ? null : winner.measure! - s.measure,
}));
return { turn, kept: winner.tine.id, cut, refused: false };
}
// the gate reads the floor from locked, protocol-owned liquidity on chain.
// if it cannot read the floor, it fails closed and the fork is refused.
declare function floorWouldHold(tine: Tine): boolean;