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

レッスン0 — OpenHL Funding を作る(永久先物 funding state machine)

問い

前コース(Precompiles)は、コントラクトが同じ Reth node 上の CLOB を read/write できる地点で終わった。だが perp はまだ perp になっていない — mark price を index(spot)に anchor する仕組みがない。永久先物には期限がないのに、価格はどうやって spot に引き寄せられるのか?

注: OpenHL コースのコードブロックは原則として手元で実行可能な形で示す。ただし <file> などのプレースホルダや答え合わせ用コマンドは、各レッスンの指示に従って置換してから実行すること。

原理(最小モデル)

  • funding 支払いが mark を index に anchor する。 Mark > index(longs が spot 比で overpay)なら longs→shorts、Mark < index なら shorts→longs を、固定 interval(HL は 1 時間)ごとに支払う。これが期限なしでも価格を spot に縛る力。
  • パイプラインは 4 段: premium → rate → capped → settlement。 (mark-index)/index(生の比率)→ /divisor(HL=8)→ clamp(±4%/interval)(ネットワーク上限)→ size × mark × capped(各 tick の決済額)。
  • float は一切使わない — consensus が壊れる。 全 validator が 完全に同じ rate を計算しなければ、1 LSB のズレでチェーンが fork する。固定小数点整数 RATE_SCALE = 1_000_000_000(parts-per-billion)で、9 桁精度を決定的に得る。
  • 純粋な state machine + 飽和演算。 I/O ゼロ・外部依存ゼロ。overflow は panic でなく saturate(最大/最小に張り付く)— consensus 中核の数学に正しい形。

具体例

1. Premium    = (mark - index) / index               ← 生の比率(無次元)
2. Rate       = Premium / divisor                     ← divisor = 8 (HL)
3. Capped     = clamp(Rate, -4%/interval, +4%/interval) ← 絶対上限
4. Settlement = size × mark × Capped                  ← 各 tick の決済 quote 額

すべて RATE_SCALE でスケールした符号付き整数の上で計算する(0.04=40_000_0000.001=1_000_000)。乗算は overflow 回避に i128 中間値、除算はその後。Premium の符号が「longs が払うか shorts が受け取るか」を決める。

失敗例(誤解)

「funding rate は f64 で計算して最後に整数化すればいい」は誤り — float は compiler / CPU / 演算順 で異なるビットパターンを生む(LLVM の FMA 分解、丸めモード差、(a*b)+c の最適化差)。1 LSB のズレのコストは チェーン fork だ:fork の別側の validator が異なる delta を決済し、balance が乖離し、次ブロックがどちらのチェーンに対しても検証されない。consensus システムでは float を一切使わず、すべて RATE_SCALE でスケールした符号付き整数で計算する。Solana の compute budget も Ethereum の EVM も同じ制約 — Determinism がすべてを決める。


ここまでで「funding が mark を anchor する」「float は consensus を壊す」は着地した。ここから先はスコープ・前提・12 レッスンのロードマップに入る。L1 以降は実際に Rust を書く。

🛑 予測。 2 つの validator が同じ funding rate を計算する。片方が f64(mark-index)/index を、もう片方が別 CPU で同じ式を計算したら、結果は bit 単位で一致するか?(答え: 保証されない。丸めモード・FMA 分解・演算順で最下位ビットが食い違いうる。funding rate の 1 LSB 不一致 = チェーン fork。だから固定小数点整数で計算する — 整数演算は全プラットフォームで bit-exact。)

終了時に手にするもの

新規 crates/funding/ crate、3 ソースファイル / 約 635 行:

  • 固定小数点 types モジュールRATE_SCALE 定数、MarkPrice/IndexPrice/Premium/Notional の金額 newtype、Position/Settlement/FundingParams
  • 純粋な compute モジュールcompute_premium / saturate_i128_to_i64 / compute_rate / apply_funding
  • clock state machineFundingClock + tick()、interval gating を担う。
  • 22 テスト:手書き 20 + proptest 2(premium 反対称性、balanced-book zero-sum)。clock 不変条件 2 つ(interval ごと settlement は最多 1 回、長時間ギャップ後の catch-up なし)を強制。

終了時にも手にしないもの(意図的な scope cut)

  • Oracle(index price の供給元) — funding は index を 入力 として受け取るだけ。
  • Liquidation(= Step 5)。
  • Basis-vs-fixed funding — HL スタイルの fixed-interval funding のみ。
  • Bridge 統合 — funding state machine は純粋な数学として完結。LiveRethEvmBridge への plug-in は capstone でプレビューし、実装は下流。

前提

  • Step 1(Consensus)/ Step 2(CLOB) をコンセプト背景として(funding は AccountId を受け取り、bridge に接続される)。Step 3(Precompiles)はスキップ可 — funding は純粋な state-machine 数学で、EVM 接続作業ではない。
  • Rust の i128 演算に慣れていること(overflow 回避の as i128 upcast を 1 回以上経験していれば十分)。
  • 永久先物 funding メカニクスに最低限の馴染み(上の 1 段落で足りる)。
  • EVM 知識は不要(precompile / コントラクト / RPC に触れない)。

不要: 動作中の openhl ノード(I/O ゼロ)/ 他 L1 チェーン経験 / 定量金融バックグラウンド。

セットアップ確認(今やる)

cd ~/code/my-openhl
git checkout main
cargo build --workspace  # baseline — L1 前に通るべき

cd ~/code/openhl-reference  # answer-key 用の別チェックアウト
git checkout cd94137

12 レッスンのロードマップ

#build するもの終了時テスト
0Orientation(本レッスン)セットアップ確認
1RATE_SCALE = 1e9 — 固定小数点方式cargo check -p openhl-funding
2金額 newtype(MarkPrice/IndexPrice/Premium/Notional型がコンパイル
3Position/Settlement/FundingParams + HL デフォルトroster 完成
4compute_premium + 符号対称性テストpremium テスト pass
5saturate_i128_to_i64 + overflow 哲学 + 最初の proptestproptest pass
6compute_rate — divisor + cap + clamprate テスト pass
7apply_funding — 符号規約 + zero-sum proptestzero-sum proptest pass
8FundingClock + tick() discrete event loopclock がコンパイル
9Interval-gating 不変条件 — 境界テスト 3 つgating テスト pass
10No-catch-up 不変条件 — 1 テストで設計哲学22 tests pass
11Capstone(recap)

マイルストーンは レッスン10 — 22 tests が全部通り、deterministic な funding パイプライン(premium→rate→settlement)が no-catch-up clock で駆動する。レッスン11 で「まだ何が足りないか(oracle / liquidation / bridge 接続)」を名指す。

答え合わせの規律

12 レッスンすべてが Funding 参照実装コミット cd94137 を引用する(funding 実装が 1 コミットにまとまっているため)。レッスン11 終了時点の answer-key diff は crates/funding/ 配下で cd94137 に一致する。

cd ~/code/openhl-reference && git checkout cd94137
diff -u ~/code/my-openhl/crates/funding/src/types.rs ./crates/funding/src/types.rs
diff -u ~/code/my-openhl/crates/funding/src/compute.rs ./crates/funding/src/compute.rs
diff -u ~/code/my-openhl/crates/funding/src/clock.rs ./crates/funding/src/clock.rs
diff -u ~/code/my-openhl/crates/funding/src/lib.rs ./crates/funding/src/lib.rs

合格基準

  • cargo test -p openhl-funding --release を 22 tests 通せる(コース完走時)。
  • なぜ funding に float を使えないか(非決定性 → fork)を 1 文で言える。
  • premium → rate → capped → settlement の 4 段を、固定小数点でなぞれる。

まとめ(3行)

  • funding 支払いが mark price を index に anchor する — Mark>index なら longs→shorts、Mark<index なら shorts→longs を固定 interval ごとに。
  • パイプラインは premium → rate → capped → settlement の 4 段。すべて RATE_SCALE = 1e9 でスケールした符号付き整数で計算 — float は 1 LSB のズレで fork を招くから使わない。
  • 純粋な state machine(I/O ゼロ)+ 飽和演算。clock 不変条件 2 つ(interval ごと最多 1 回、catch-up なし)を強制する。