Skip to content

LAST LIGHT ​

LAST LIGHT is the programmable liquidity component of the protocol, a Uniswap v4 hook attached to the VSPR/USDC pool.

Responsibilities ​

  • session-aware pool behavior
  • dynamic fees
  • final-hour activation
  • fee normalization after the window
  • eligible protocol revenue routing

Normal Session ​

text
fee = baseFee

Final Hour ​

During the final 60 minutes of the configured equity session:

text
fee = baseFee + ramp(timeToClose)

As timeToClose approaches zero, the fee approaches its configured closing level.

Where the fee goes ​

The mechanism is deterministic: the Hook reads current session state and applies predefined logic rather than relying on a daily manual trigger. What it takes is paid out inside the swap, to a fixed address outside the protocol. It never reaches the reserve.

Current Schedule ​

As implemented in hooks/LastLight.sol:

Session stateFee
Open, 09:30 to 15:00 ET30 bps
Last light, the final 60 minutes30 bps at T-60, rising linearly to 200 bps at T-0
After the close, closed, pre-market100 bps
15:40 ET
Last light
143.33 bps
3010020000:00 04:00 08:00 12:00 16:00 20:00 24:00 openclose
Tue Sep 15, New York time. The shaded band is the session, the brighter one is last light.
text
fee = 30 + 170 x (3600 - secondsToClose) / 3600   (bps)

The pool fee is updated only when the schedule has moved at least 5 bps from the last applied fee. Half of every fee (the protocol share, owner-settable) is taken by the hook on the unspecified currency and paid, in the same swap, to feeRecipient.

The opening taper ​

The session schedule above is about the close. The taper is about the launch: a second cut, measured from the moment the pool was created, that starts high and settles at a flat 2%. The schedule below is what taperSchedule() returns on the deployed hook.

Time since the pool openedBuySell
First 60 seconds10%15%
The next 60 seconds5%5%
From 120 seconds on, permanently2%2%

The tiers are constants in the contract and the clock starts in afterInitialize, so nothing can raise them afterwards and no one can burn through the opening tier with a dust swap: it expires on the clock whether anyone traded or not. The taper is paid the same way as the protocol share, in the same call.

There is nothing to settle. In afterSwap the hook takes the protocol share plus the taper on the unspecified currency and hands it at once to feeRecipient, an immutable address set at construction, outside the protocol: the dev wallet. The hook never holds a token, there is no accumulator, no sweep and no keeper. Each paying swap emits Captured(cycleId, currency, amount, feePips) and, when a taper applied, Tapered(cycleId, currency, amount, bps, isBuy); the amounts are also counted per 8-hour cycle (accruedThisCycle, cycles, paidCount, totalPaid0, totalPaid1) for the record only.

The hook books nothing with the Distributor: what it takes is not reserve backing, so it never mints VSPR and never feeds the reserve. The protocol's own revenue is the bond surplus:

text
reward = min(bond proceeds, excess reserves)

If no bond sold above backing, the cycle pays nothing.

Everything settles at the close.