FABRKNT
Step 4. Funding:決定論的数学パイプラインと Funding ステートマシンの構築
Capstone
レッスン 12 / 12·CONTENT20 分40 XP
コース
Step 4. Funding:決定論的数学パイプラインと Funding ステートマシンの構築
レッスンの役割
CONTENT
順序
12 / 12

レッスン11 — Capstone — 築いたもの、先送りしたもの、次にくるもの

問い

Funding pipeline を記憶からホワイトボードに描けるか? v0 で 意図的に 先送りした項目を名指し、なぜ crates/funding/ の守備範囲外かを説明できるか? このレッスンにコードはなし — メンタルモデルだけだ。

原理(最小モデル)

pipeline は 1 本の決定論的な変換: (mark, index) → premium → rate → settlements、それを clock が「十分な時間が経過したか?」で gate する。crate は pure な state machine(I/O ゼロ、外部依存は openhl-clobAccountId のみ)で、すべて RATE_SCALE = 1e9 の符号付き固定小数点整数で計算し、overflow は saturate する。

具体例

   MarkPrice ──┐
   IndexPrice ─┴─► compute_premium ─► Premium
                                        │
   FundingParams ─────────► compute_rate ─► FundingRate (±rate_cap に clamp)
                                        │
   &[Position] ──────────► apply_funding ─► Vec<Settlement> { account, delta: Notional }
                                                              → bridge → balance 更新 (将来)

   ╔══ FundingClock::tick ══════════════════════════════════╗
   ║  guard: now ≥ last_settled_at + interval_secs?          ║
   ║    no → None /  yes → 上の pipeline 実行、now に advance    ║
   ╚════════════════════════════════════════════════════════╝

この Vec<Settlement> レーンは Step 2(CLOB)の Vec<Fill> と同じく、まだ EVM 本流(BlockExecutor)の外側を並走している — 直交レーンとして先に独立実装し、統合点を後で合わせるのが openhl の一貫した設計規律。

失敗例(誤解)

「funding crate に oracle / balance 更新 / liquidation も入れれば self-contained で便利」は誤り — それぞれが独自の関心事(oracle は staleness/aggregation、balance は storage、liquidation は別 cadence の state machine)を持ち込み、pure な state machine を汚す。これらは bridge レイヤー(将来)が tick() に接続する。crate は計算するだけ、永続化も I/O もしない。

各モジュールが届けたもの

  • Determinism + 型(レッスン1〜3) — 固定小数点の語彙: RATE_SCALE = 1e9、9 newtype(MarkPrice/IndexPrice/Premium/FundingRate/Notional/PositionSize/Position/Settlement/FundingParams)、hyperliquid_default()(3600s / ±4% / divisor 8)。学び: newtype が引数順バグをコンパイル時に防ぐ、符号規約は型の定義 doc に。
  • 純粋な compute(レッスン4〜7) — stateless な数学: compute_premium(i128 中間値・saturate)/ compute_rate(割ってから clamp・defensive .abs())/ apply_funding(単項マイナスで longs-pay-shorts・flat フィルタ)/ saturate_i128_to_i64。15 テスト(手書き 13 + proptest 2)。学び: panic/wrap/saturate のうち saturate だけが consensus-safe。
  • Clock state machine(レッスン8〜10) — discrete event loop: FundingClock/FundingTick/tick()、7 テスト(guard / 境界 / interval 持続 / no-catch-up)。学び: composition テストが接続ミスを捕まえる、state machine は multi-call テストが要る、設計哲学は doc/コード/テストの 3 箇所に。

正直に先送り(意図的な scope cut)

5 項目、どれも実プロダクションギャップ:

  1. Oracle 統合compute_premiummark/index を入力に取るだけ。価格を 取得 する方法(CLOB mid / Pyth / Chainlink、staleness チェック、aggregation)はなし。bridge レイヤーが tick() 直前に読む。
  2. Balance 更新tick()Vec<Settlement> を返すだけ。delta を balance に 適用 するのは bridge(funding crate は storage-free)。
  3. Liquidation(= Step 5) — settlement は balance を負まで押しうるが、吸収可否チェックや処理はなし。独自の不変条件(insurance fund / ADL / mark トリガー)と別 cadence(funding は時間単位、liquidation はブロック単位)を持つ別 crate。
  4. Multi-market funding — 単一マーケットの FundingClock 1 つ。複数マーケットは bridge の HashMap<MarketId, FundingClock> で管理(crate は 1 マーケットに正しければ十分)。
  5. EVM event としての funding — コントラクトが funding tick を 観測 する手段なし。非 EVM コードから event を emit する plumbing は bridge の関心事。

次に来るもの

複雑度順に 4 つ:

  1. Oracle adapter(2-3 日)crates/oracle/、複数ソースを staleness チェック付きで aggregate し current_index_price() -> Option<IndexPrice> を公開。難しいのは threshold 決め。
  2. Bridge 側の funding tick(1 週間)FundingClockLiveRethEvmBridge に組み込む。mark を CLOB から、index を oracle から、position をストアから読み tick()、settlement を balance に適用。ほとんど plumbing、funding crate は自己完結のまま。
  3. Liquidation エンジン(3-4 週間)crates/liquidation/、funding-tick 後の balance を監視し under-margined を insurance fund / ADL waterfall で処理。独立した 1 コース規模。
  4. Multi-market manager(1 週間)crates/markets/HashMap<MarketId, FundingClock> でマーケットごとに dispatch。価値はマーケットごとの isolation。

このコースの位置(L1 Architect トラック)

  • コース1〜5(Reth internals): pipeline / payload / NodeBuilder / evm crate / RPC。
  • Step 1(Consensus)/ Step 2(CLOB): Malachite 統合 → マッチングエンジン。
  • Step 3(Precompiles): カスタム precompile 経由の EVM ↔ CLOB ブリッジ。
  • Step 4(Funding、本コース): funding state machine。pure な state、I/O なし — Step 3 の bridge plumbing と対をなす位置づけ。
  • Step 5(Liquidation): funding / oracle / liquidation を LiveRethEvmBridge に組み込み、動作する perp DEX として組み上がる。

ここで内面化したパターンは perp funding を超えて一般化する: consensus システムの固定小数点演算(実数 x をスケール SX = x·S にし、積は wider 型で受けて最後に S で割り戻す — fee なら S=10_000、vesting なら S=86_400)/ saturation(consensus-safe な唯一の overflow 戦略)/ 意味的区別のための newtype / レイヤー化コードの composition テスト / 設計哲学を doc・コード・テスト・散文に分散。

最終答え合わせ

cd ~/code/openhl-reference
git checkout cd94137
diff -u ~/code/my-openhl/crates/funding/ ./crates/funding/ --recursive

コース完走後、crates/funding/ ディレクトリ全体が openhl の cd94137 HEAD と byte-identical に一致する。

main に戻す:

git checkout main

まとめ(3行)

  • pipeline は (mark,index) → premium → rate → settlements の決定論的変換を FundingClock が interval で gate するだけ。pure な state machine(I/O ゼロ、外部依存は AccountId のみ)。
  • 3 モジュールの成果: 固定小数点の語彙 → stateless な数学(saturate)→ no-catch-up な clock。22 tests(手書き 20 + proptest 2)が cd94137 に一致。
  • 5 つの先送り(oracle / balance 更新 / liquidation / multi-market / funding-as-EVM-event)はすべて bridge レイヤーまたは別 crate の関心事 — drop-in 可能な、Hyperliquid 型の perp funding crate が手元にある。