フックとアンチスナイプ
Uniswap v4のフックとは、スワップの特定のタイミングでPoolManagerが呼び出すコントラクトです。StockFunHookの現在の実装は6つの権限を使用します。beforeInitialize、beforeAddLiquidity、beforeSwap、afterSwap、そして手数料を差し引くことを可能にする2つのデルタ権限です。2026-10-02以降、そのアドレスはv4の14の権限すべてを備えており、現在の実装が使用しないコールバックは何もせずに通過します。
アドレスが権限をエンコードする
v4は、フックをいつ呼び出すかを知るために、そのアドレスの下位ビットを読み取ります。そのため、アドレスは自由に選べません。宣言された権限とビットが一致する値が見つかるまで、CREATE2を使ってマイニングされます。
2026-10-02以降、マイニングされるのはプロキシのアドレスで、14の権限ビットすべてが立っています。アップグレードは、そのアドレスを動かすことなく背後の実装を置き換えるため、再マイニングが必要になることはなく、今後の実装はどのコールバックでも使用できます。現在の実装は、使用しないコールバックを何もせずに通過させます。それらのコールバックは自身のセレクタを返し、デルタが期待される場合はゼロを返します。プロキシの初期化処理は、自身のアドレスがすべてのビットを備えていることを確認します。
実務上の帰結として、マイニングされたアドレスは、プロキシのバイトコードと、実装のアドレスを含むそのコンストラクタ引数に依存します。新しくデプロイする場合は再マイニングが必要です。foundry.tomlがbytecode_hash = "none"を設定しているのもこのためです。これがないと、マイニングしたアドレスがデプロイされたコントラクトと一致しなくなります。
2026-10-01に追加されたbeforeAddLiquidity権限は、ビットそのものを変えました。アドレスは再マイニングされ、その日より前に行われたデプロイはすべて古いものになっています。2026-10-02のプロキシは、ビットを再び変えました。その日より前に行われたデプロイも、すべて古いものになっています。
手数料の徴収
買いの場合、手数料はスワップが行われる前に、beforeSwapで、入ってくるETHから徴収されます。フックは自らの取り分をPoolManagerから引き出し、それを買い手に負担させるデルタを返します。StockFunのルーターと流動性のロックは、スワップの前に買い手のETHをPoolManagerへ支払うため、それらを経由する買いが、PoolManagerがすでに保有しているETHに手をつけることは決してありません。
それ以外のv4ルーターも、同じ率のタックスを支払います。しかし、v4-peripheryのV4Routerがデフォルトのエンコーディングで行うように、スワップの後に買い手のETHを決済するルーターでは、タックスがPoolManagerがすでに保有しているETHから徴収され、タックスの方が大きいとその買いは失敗します。これは、たとえばテストネットのもののように、ETHをわずかしか保有していないPoolManagerで起こりえます。インテグレーターは、公式ルーターと同じように、スワップの前に買い手のETHを払い込むべきです。売りは影響を受けません。2026-10-01のセキュリティパイプラインが、この制限を文書化しました。代わりにタックスをPoolManagerのクレームとして徴収すれば、すべてのルーターについてこの制限はなくなりますが、トレジャリーの2 %は、取引中に支払われるものから、計上されて後で支払われるものに変わります。2026-10-05、オーナーは、タックスを現在の徴収方法のまま維持することを決定しました。
売りの場合は、金額が確定した後、afterSwapで、出ていくETHから徴収されます。
どちらの場合も、フックは即座に配分します。トレジャリー、クリエイター、チーム、バイバックです。取引中に出ていくのはトレジャリーの項目だけで、マーケットのボールトへ送られます。他の3つの項目はフック上に計上され、取引の外で支払われます。
2026-10-05以降、トレジャリーの項目を拒否するボールトが、取引を失敗させることはなくなりました。フックはその額をそのボールトへの未払い分として保持し(treasuryOwed、イベントTreasuryOwed)、すべての買いと売りは続きます。誰でもpayTreasuryでそのボールトへの債務を支払うことができ、ボールトがまだ拒否している間は、この呼び出しは失敗して債務を保持します。キーパーは毎サイクルそれを試みます。アンチスナイプの超過分も同じルールに従います。それまでは、送金は明示的に失敗していました。たとえば欠陥のあるアップグレードの後で受け取れなくなったボールトは、売りも含めて、そのマーケットのすべての取引を失敗させていました。
クリエイターの取り分はプル型です。フック上にマーケットごとに蓄積され、クリエイターは好きなときに、マーケットごとに1つのトランザクションで請求します(claimCreatorFees)。2026-10-05以降、自らETHを受け取れないクリエイター、つまりETHを受け取る手段のないコントラクトは、別のアドレスへ請求します(claimCreatorFeesTo)。これができるのはクリエイターだけです。
2026-10-01以降、チームとバイバックの取り分も同じ方法で、それぞれ1つの残高として計上され、claimTeamFees()とclaimBuybackFees()によって支払われます。これらは誰でも呼び出せますが、支払い先は、請求の時点でファクトリーが指定しているチームとバイバックのウォレットだけです。BuybackBurnerは、各バーンの開始時に、自分の残高を自ら引き取ります。ETHを拒否するウォレットは、自分への支払いを遅らせるだけです。その請求は失敗し、残高はフック上にとどまります。
それまでは、この2つの取り分は取引中に送金され、送金が失敗した場合にはエスクローへのフォールバックがありました。2026-09-29のセキュリティ監査は、送金を受け入れたうえでPoolManagerを呼び出すウォレットが、すべてのプールの取引を停止させうることを示しました。エスクローはなくなりました。
取引と取引の間にフックが保有しているものは、誰かに支払われるべきものです。クリエイターの残高、チームとバイバックの残高、そしてボールトへの債務です。PoolManager以外の誰かがフックに送ったETHは、紛れ込んだ資金(strayEth)として別に数えられます。2026-10-05以降、StockFunのオーナーは、紛れ込んだ資金を取り出すことができます(rescue)。ETHはその額までで、トークンはどれでも取り出せます。フックがトークンを保有することは決してないからです。フックが負っているものは、この方法で出ていくことはできません。呼び出しなしに強制的に送り込まれたETHは数えられず、アップグレードを待ちます。
流動性を追加するのはロックだけ
2026-10-01以降、beforeAddLiquidityは、StockFunのプールへの流動性の追加を、流動性のロックによるものを除いてすべて拒否します。
現在の価格のすぐ脇に置かれたポジションは、指値注文として機能します。トレーダーのスワップがそれを通過して変換し、タックスを支払うのはトレーダーである一方で、ポジションの所有者は、5 %も、最初の10ブロックではアンチスナイプのタックスも一切支払うことなく、そのポジションを追加し、取り除きます。2026-09-29のセキュリティ監査はこれを再現しました。プールはデフォルトでLP手数料を課さないため、サードパーティのポジションを必要とする正当な用途はありません。
ロック自身による手数料の回収は、流動性のデルタがゼロで、流動性を取り除く経路を通ります。現在の実装はこの経路をそのまま通すため、影響を受けません。終了モードによる回収も同様で、同じ経路を通ってポジションを取り出します。2つのポジションによるローンチを参照してください。
逓減型アンチスナイプ
v4のプールは、初期化された瞬間から稼働します。対策がなければ、作成直後の最初の数ブロックはボットに奪われてしまいます。2026-09-28以降、これらのブロックでは、買いにも売りにも同じく、より重いタックスがかかり、ブロックごとに下がっていきます。デフォルトの設定では次のとおりです。
| ローンチからのブロック | タックス |
|---|---|
| 1 | 80 % |
| 2〜10 | 72, 64, 56, 48, 40, 32, 24, 16, 8 % |
| 11+ | 通常どおり、5 % |
開始ブロックで購入するボットは、即座に80 %を支払います。スナイプは損になります。
3つの点について説明が必要です。
クリエイターのローンチ時の購入には識別チェックが不要です。LiquidityLockが実行する唯一のスワップは、自身の作成コールバック内での、クリエイターの任意の購入です。したがって、「呼び出し元がロックである」ことは「作成トランザクションの内部にいる」ことを意味し、その購入には通常の5 %がかかります。
超過分には独自の行き先があります。通常の5 %は、いつもどおりの配分に従います。それを超える部分はマーケットのトレジャリーに入り、したがって次のエアドロップでホルダーに渡ります。$STOCKFUNマーケットでは、フック上のチームの残高に入り、claimTeamFees()によって支払われます。
ホワイトリストには識別が必要であり、そこが繊細な部分です。フックに見えるのはルーターであり、買い手ではありません。そのためStockFunのルーターは、呼び出し元のアドレスをフックデータに含めて渡し、フックは呼び出し元が公式ルーターである場合に限りそのフィールドを信頼します。公式ルーターとは、ファクトリーに記録されているルーターのことで、オーナーはこれをいつでも変更できます(2026-09-28に受け入れ済み)。このプロトコルでは、どこにもtx.originを使用していません。
文書化された制限事項:最初の10ブロックの間にサードパーティのアグリゲーターを経由してルーティングするホワイトリスト登録アドレスは、免除の対象になりません。
ホワイトリスト
マーケットのクリエイターが設定します。リスト上のアドレスは、アンチスナイプのブロックの間、通常の5 %を支払います。2026-09-28までは、まさにインサイダーの優位性にならないよう、リストはオーナーが保持し、すべてのマーケットで共通でした。現在では、クリエイターは自分のウォレットを免除できます。2026-09-28に承認済み:リストは作成トランザクション内で確定し、公開され、イミュータブルで、上限はデフォルトで20アドレスです。
$STOCKFUNマーケット
逓減するタックスはここでも適用されます。$STOCKFUNには外部のクリエイターがいないため、その超過分はチームの請求可能な手数料となり、そのホワイトリストはローンチ時にオーナーが設定します。
設定
2026-10-05以降、このページのすべての数値は、StockFunのオーナーがフック上でsetTaxSettingsによって変更する設定です。タックス(デフォルトで5 %)、その項目(ローンチされたマーケットでは2 / 2 / 0.5、$STOCKFUNでは2 / 2.5で、バイバックが残りを受け取る)、アンチスナイプの開始時のタックス(80 %)、ブロックごとの減少幅(8ポイント)、継続するブロック数(作成ブロックを含めて10)、そしてホワイトリストの最大数(20アドレス)です。
変更は、アンチスナイプのブロック内にあるプールも含め、すべてのプールで次のスワップから適用されます。逓減は、プールのローンチブロックを起点に、その時点で有効な設定で計算されます。設定がどうであれ、アンチスナイプが通常のタックスより低い率を課すことは決してありません。この設定は、100 %を超える率と、項目の合計がタックスを超える配分表を拒否します。ホワイトリストの上限はマーケットの作成時に確認され、すでに設定されたリストはそのまま残ります。
アップグレード
2026-10-02以降、StockFunのオーナーはフックを即時発効でアップグレードできます。このページで説明しているタックス、その配分、アンチスナイプ、ホワイトリストは、現在の実装のものです。アップグレードしてもフックのアドレスは変わらず、同じPoolManagerを維持しなければなりません。フックが読み取り、誰がフックをアップグレードできるかを決めるファクトリーは、実装の中に固定されています。