Docs
What the two contracts do, in the order you would need it. Not a summary of a whitepaper · the code, described.
01 · Architecture
A B-20 asset, a hook and a position manager. No proxies, no upgrade path, no admin.
| Contract | What it is | State it keeps |
|---|---|---|
| VELVET | B-20 on Base, fixed supply 1e9, admin-less after the deploy | balances |
| VelvetHook | the v4 hook: the clock and the toll | one pool id, four counters |
| VelvetLpManager | the single-side position | the position itself |
02 · The clock
SessionClock is a pure library. Given a timestamp it answers three things:
is New York open, how long has it been shut, and when is the next bell.
session 09:30 to 16:00 New York, Monday to Friday
daylight second Sunday of March to first Sunday of November, 02:00 local
holidays New Year, MLK, Presidents, GOOD FRIDAY, Memorial, Juneteenth,
Independence, Labor, Thanksgiving, Christmas
observance Saturday -> the Friday before, Sunday -> the Monday after
half days 13:00 close on July 3rd, the day after Thanksgiving, Christmas Eve
Good Friday moves with Easter, so it is computed - Meeus/Jones/Butcher - and not read from a table that would run out. The whole library is checked against Python's own zoneinfo and calendar modules, timestamp by timestamp, in the test suite.
03 · The toll
toll = size x TOLL_MAX_BPS/10000 x min(staleness, MAX_GAP) / MAX_GAP TOLL_MAX_BPS = 300 MAX_GAP = 235,800 s (Friday close to Monday open)
Zero while the market is open. Linear in the blackout. Capped at 3%, and the cap is only reached in a gap at least as long as a weekend - a Monday holiday runs past it and is clamped, never more.
04 · The hook
Two callbacks. The toll is always taken on the ETH leg, so it is knowable up front
when ETH is the exact side (beforeSwap) and read off the settled delta when it
is not (afterSwap). Between the two, every swap is charged exactly once.
The charge is minted as a claim, donated to the pool, and the claim burned - three calls, one transaction. If nothing is in range there is nowhere honest to put it, so it is not taken at all rather than held.
marketOpen() is New York open right now stalenessNow() seconds since the closing bell, 0 while open tollBps() the rate at this instant tollBpsAt(ts) the rate at ANY timestamp - pure, public, checkable quote(size) (toll in wei, bps, open) nextOpen() the next bell, as a timestamp
05 · The pool
One Uniswap v4 pool on Base, ETH/VELVET, fee 0.30%, tick spacing 60, opened single side: the range sits entirely below the price, so the launch puts in the whole float and not one wei of ETH. The hook is pinned to that pool once and can never be pointed at another.
06 · Reading it yourself
cast call $HOOK 'marketOpen()(bool)' --rpc-url https://mainnet.base.org cast call $HOOK 'stalenessNow()(uint256)' cast call $HOOK 'tollBps()(uint256)' cast call $HOOK 'tollBpsAt(uint256)(uint256)' 1789392599 cast call $HOOK 'quote(uint256)(uint256,uint256,bool)' 1000000000000000000
This site runs the same calendar in JavaScript, and that copy is diffed against the contract over a full year of timestamps - both daylight switches, every holiday - with zero disagreements. It is not a re-implementation you have to trust; it is one you can check.
07 · What it cannot do
- No owner, no admin, no setter, no pause, no upgrade.
- No mint function on the token: the supply that exists at the deploy is all there is.
- The hook holds nothing between transactions and has no
receive(). - The hook is pinned to one pool, once. It cannot be re-aimed at a book somebody else controls.
- Nothing can change the schedule. There is no calendar to update, because there is nobody who could.
08 · Where it is imperfect
Said plainly, because a mechanism that hides its edges is a mechanism you cannot price:
- Unscheduled closures. A hurricane day or a circuit breaker is not in the calendar; the contract will read that day as open and charge nothing.
- The rule is linear, and markets are not. The first hour after the bell and the last hour before it are priced the same way, on the same slope.
- It prices the blackout, not the volatility. A quiet weekend and a weekend with news in it cost exactly the same.