configurator について
Continuous Clearing Auction(CCA)のスマートコントラクト設定を行う Claude Code 向けスキルです。質問をまとめて収集・検証し、値を計算して、MCP ツールで供給スケジュールを生成できます。
主な機能
- 01質問をまとめたパラメーター収集
- 02アドレス・チェーン・数値の検証
- 03オークション時間と Q96 価格の計算
- 04供給スケジュールの生成
- 05設定 JSON と概要の出力
活用シーン
- 01トークンオークションの設定
- 02オークション供給スケジュールの生成
- 03既存設定の確認やデプロイ
MCP 対応
MCP サーバーが稼働している場合、オークションとプレセールのブロック数を指定して `cca-supply-schedule__generate_supply_schedule` ツールを呼び出します。ツールが使えない場合の Python による代替方法も記載されています。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ uniswap/ uniswap-ai --skill configuratorインストール後、Claude Code で/configuratorを入力して読み込まれたか確認します。
詳細
CCA の設定
公平で透明性の高いトークン配布のため、Continuous Clearing Auction(CCA)スマートコントラクトのパラメーターを設定します。
ランタイムの互換性: このスキルでは、対話型プロンプトに
AskUserQuestionを使用します。実行環境でAskUserQuestionが利用できない場合は、自然言語での会話を通じて同じパラメーターを収集してください。
Claude Code への指示
ユーザーがこのスキルを呼び出したら、AskUserQuestion を使った一括対話型フォーム設定フローを案内します。ユーザーとのやり取りを最小限に抑えるため、パラメーターはまとめて収集してください。
一括対話型フォームのルール
- 質問をまとめる - 1 回の AskUserQuestion 呼び出しで最大 4 つの質問をします
- 直接入力を許可する - カスタム値が必要なフィールド(アドレス、数値)については、以下のようにします。
- 「まだありません」または「今回はスキップ」の選択肢を用意します
- 「その他」の選択肢(自動で用意されます)を使って、カスタム値を直接入力できるようにします
- 「X はありますか?」と単独で質問することは絶対にしないでください
- 回答を保存する - 収集したすべての値を設定オブジェクトに記録します
- 収集後に検証する - 各バッチの後、次に進む前にすべての入力を検証します
- 進捗を表示する - 各バッチの後、収集済みのパラメーターと残りのパラメーターを表示します
入力検証ルール
上記のルール 4 では、各バッチの後に検証するよう指定しています。検証とは、以下の内容を指します。ほとんどの値は、以下に示す選択肢から選んで指定されますが、いずれの値も自由入力で指定されることがあります。AskUserQuestion が各質問で提供する「その他」の選択肢を使う場合や、上記のランタイム互換性の代替手段が適用され、AskUserQuestion が利用できない環境で通常の会話を通じて指定する場合です。カスタム RPC エンドポイントがその最もわかりやすい例です。Network の質問には名前付きネットワークが表示され、エンドポイントの入力欄はありませんが、パブリックエンドポイントを選ばないユーザーは、「その他」または会話を通じてエンドポイントを指定します。設定ファイルに書き込む前、または curl コマンドに埋め込む前に、以下のチェックに照らしてすべての値を検証してください。例外を探してはいけません。このスキルが提示した選択肢のいずれかと実際に一致する値は、すべてのチェックにそのまま合格します。また、会話による代替手段では、そもそも値がどこから来たのかを確認する方法がありません。
- Ethereum アドレス(
token、currency、tokensRecipient、fundsRecipient、validationHook):^0x[a-fA-F0-9]{40}$に一致する必要があります。一致しない場合は拒否します - Chain ID:サポート対象のチェーン一覧(1、130、1301、8453、42161、11155111)に含まれている必要があります
- 数値(供給量、価格、ブロック、MPS、ブロック差分):0 以上で、
^[0-9]+\.?[0-9]*$に一致する必要があります - RPC エンドポイント URL:利用可能なパブリック RPC の表にあるパブリックエンドポイントを優先してください。ただし、カスタムエンドポイントは、どのような方法で指定された場合でも、ブロック番号の取得に記載された
curlコマンドに渡す前に、https://スキームを使用し、以下のルールにあるメタ文字や空白を含まない必要があります。「ユーザーが指定した値で、表に載っていない」というのは例外になりません - 拒否する入力:シェルのメタ文字または空白を含む入力。対象は
;、|、&、$、`、(、)、>、<、\、'、"、スペース、タブ、改行です。$(...)とバッククォートは二重引用符の内側でもコマンドを実行し、スペースは 1 つの値を複数のcurlフラグに分割するため、どちらも埋め込みに使うことは決して安全ではありません。問題のある文字を取り除いて処理を続けるのではなく、処理を中止し、どの値のどの文字が原因で失敗したかを報告してください - 検証せずに生のユーザー入力をシェルコマンドに渡すことは絶対にしないでください。ユーザーに提示するコマンドでは、埋め込む値を必ず二重引用符で囲んでください
いずれかのチェックに失敗した値は、設定ファイルにも書き込みません。deployer スキルはそのファイルを読み取り、各フィールドを forge および cast コマンドに埋め込みます。したがって、ここで検証されていない値を保存すると、そこでコマンドインジェクションが発生します。
設定フロー
以下のバッチに分けてパラメーターを収集します。
バッチ 1:タスクの選択(1 問)
質問 1:タスクの種類
- プロンプト:「CCA で何を行いますか?」
- 選択肢:「オークションパラメーターを設定する」、「供給スケジュールのみを生成する」、「既存の設定を確認する」、「既存の設定をデプロイする」
収集後:「オークションパラメーターを設定する」以外を選択した場合は、該当するセクションに進みます。
バッチ 2:基本設定(4 問)
質問 1:ネットワーク
- プロンプト:「デプロイ先のネットワークを選択してください。」
- 選択肢:「Ethereum Mainnet」、「Unichain (Mainnet)」、「Unichain Sepolia (Testnet)」、「Base」、「Arbitrum」、「Sepolia」
- 保存:選択した通貨に応じた
chainId、blockTime、rpcUrl、currencyDecimals
質問 2:トークンアドレス
- プロンプト:「オークションにかけるトークンは何ですか?」
- 選択肢:「トークンはまだデプロイされていない」(プレースホルダー)、カスタムアドレス(「Other」から指定)
- 検証:42 文字で、0x から始まる必要があります
- 保存:
token
質問 3:総供給量
- プロンプト:「オークションにかけるトークン数はいくつですか?」
- 選択肢:「1 億トークン(18 桁の小数)」、「10 億トークン(18 桁の小数)」、「100 億トークン(18 桁の小数)」、カスタム(「Other」から指定)
- 検証:1e30 wei 以下である必要があります
- 保存:
totalSupply
質問 4:通貨
- プロンプト:「入札者が使用する通貨は何ですか?」
- 選択肢:「ETH(ネイティブ)」、「[network] 上の USDC」、「[network] 上の USDT」、カスタム ERC20(「Other」から指定)
- 検証:42 文字で 0x から始まるか、address(0) である必要があります
- 保存:
currency
**収集後:**すべての入力を検証し、基本設定の概要を表示します。
バッチ 3:タイミングと価格設定(4 問)
質問 1:オークション期間
- プロンプト:「オークションの実施期間はどのくらいですか?」
- 選択肢:「1 日」、「2 日」、「3 日」、「7 日」、カスタムのブロック数(「Other」から指定)
- ネットワークのブロック時間に基づいてブロック数を計算します
- 保存:
auctionBlocks
質問 2:プレ入札期間
- プロンプト:「プレ入札期間を設けますか?(この期間中はトークンを販売しません)」
- 選択肢:「プレ入札期間なし(0 ブロック)」、「12 時間」、「1 日」、カスタムのブロック数(「Other」から指定)
- ネットワークのブロック時間に基づいてブロック数を計算します
- 保存:
prebidBlocks
質問 3:最低価格
- プロンプト:「開始時の最低価格はいくらですか?(トークン 1 枚あたりの通貨の比率)」
- 選択肢:「0.10x(1:1 の比率の 10%)」、「0.01x(1:1 の比率の 1%)」、「0.001x(1:1 の比率の 0.1%)」、カスタム比率(「Other」から指定)
- 小数桁の差を考慮して Q96 値を計算します:
Q96 * ratio / 10^(tokenDecimals - currencyDecimals) - USDC(小数 6 桁)と 18 桁の小数のトークンの場合:
Q96 * ratio / 10^12 - ネイティブ ETH(小数 18 桁)と 18 桁の小数のトークンの場合:
Q96 * ratio / 10^0 = Q96 * ratio - 保存:
floorPriceRatio、floorPrice(Q96)、tokenDecimals、currencyDecimals
質問 4:ティック間隔
- プロンプト:「最低価格に対する割合で、ティック間隔を指定してください。」
- 選択肢:「最低価格の 1%(推奨)」、「最低価格の 10%」、「最低価格の 0.1%」、カスタムの割合(「Other」から指定)
- 計算:
tickSpacing = int(floorPrice * percentage) - 重要:ティック間隔で割り切れるよう、最低価格を切り下げます:
roundedFloorPrice = (floorPrice // tickSpacing) * tickSpacing- 確認:
roundedFloorPrice % tickSpacing == 0が真である必要があります
- 検証:ティック間隔は最低価格の 1 ベーシスポイント以上である必要があります
- 保存:
tickSpacingPercentage、tickSpacing(Q96)、roundedFloorPrice
**収集後:**入力を検証し、最低価格が割り切れることを確認し、Q96 値を計算して表示し、タイミングの概要を表示します。
バッチ 4:受取先と開始(4 つの質問)
質問 1:トークンの受取先
- プロンプト:「売れ残ったトークンの送付先はどこですか?」
- 選択肢:「資金の受取先と同じ」、カスタムアドレス(「その他」経由)
- 検証:0x で始まる 42 文字である必要があります
- 保存先:
tokensRecipient
質問 2:資金の受取先
- プロンプト:「調達した資金の送付先はどこですか?」
- 選択肢:「トークンの受取先と同じ」、カスタムアドレス(「その他」経由)
- 検証:0x で始まる 42 文字である必要があります
- 保存先:
fundsRecipient
質問 3:開始時刻
- プロンプト:「オークションはいつ開始しますか?」
- 選択肢:「1 時間後」、「6 時間後」、「24 時間後」、カスタムブロック番号(「その他」経由)
- RPC から現在のブロック番号を取得して計算します
- 保存先:
startBlock - 計算:
endBlock = startBlock + prebidBlocks + auctionBlocks、claimBlock = endBlock
質問 4:必要な最低資金額
- プロンプト:「卒業に必要な最低調達通貨額を設定しますか?」
- 選択肢:「最低額なし(0)」、「100 ETH」、「1000 ETH」、wei 単位のカスタム金額(「その他」経由)
- 保存先:
requiredCurrencyRaised
収集後: アドレスを検証し、RPC から現在のブロック番号を取得して、ブロックのタイムライン全体を計算します。
バッチ 5:オプションのフック(1 つの質問)
質問 1:検証フック
- プロンプト:「検証フックコントラクトを使用しますか?」
- 選択肢:「検証フックなし」、カスタムフックアドレス(「その他」経由)
- 検証:指定する場合は、0x で始まる 42 文字である必要があります
- 保存先:
validationHook
収集後: 指定されている場合は、フックアドレスを検証します。
ステップ 6:供給スケジュールを生成する
MCP サーバーが起動していない場合は、起動手順を提示します。
# Navigate to MCP server directory
cd packages/plugins/uniswap-cca/mcp-server/supply-schedule
# Run setup script (first time only)
chmod +x setup.sh
./setup.sh
# Start the MCP server
python3 server.py
MCP サーバーが起動したら、収集したパラメーターを指定して cca-supply-schedule__generate_supply_schedule MCP ツールを呼び出します。このツールは JSON オブジェクトを受け取ります。
{
"auction_blocks": 86400,
"prebid_blocks": 0
}
値を、ユーザーから収集した実際の auctionBlocks と prebidBlocks に置き換えます。
MCP ツールを利用できない場合は、フォールバックの Python アルゴリズムを直接使用します(「供給スケジュールの設定」セクションを参照)。
保存先:supplySchedule
ステップ 7:設定を生成して表示する
すべてのパラメーターを収集し、供給スケジュールを生成したら、CLI 出力に完全な JSON 設定を表示します。
{
"[chainId]": {
"token": "...",
"totalSupply": ...,
"currency": "...",
"tokensRecipient": "...",
"fundsRecipient": "...",
"startBlock": ...,
"endBlock": ...,
"claimBlock": ...,
"tickSpacing": ...,
"validationHook": "...",
"floorPrice": ...,
"requiredCurrencyRaised": ...,
"supplySchedule": [...]
}
}
ファイルを自動的に作成しないでください。 JSON をコピーするか、保存するファイルパスを指定するか、ユーザーに選んでもらいます。
ステップ 8:概要を表示する
次の項目を含む、包括的で整形された概要をユーザーに表示します。
- ネットワークとチェーン ID
- トークンと通貨の詳細
- ブロックのタイムライン(開始、終了、請求)と人間が読みやすい時刻
- 価格設定(下限価格、ティック間隔)の Q96 形式と比率形式
- 受取先(トークン、資金)
- 供給スケジュールの概要(フェーズの合計数、最終ブロックの割合)
- 検証チェックリスト(すべての検証ルールの合格/不合格)
ステップ 9:次の手順
次に何をするか、ユーザーに尋ねます。
- 「ファイルに保存」(ファイルパスを尋ねます。デフォルト:
script/auction-config.json) - 「デプロイ手順を表示」(deployer スキルの使用を提案します)
- 「設定を変更」
- 「終了」(そのまま終了します。ユーザーは CLI 出力から JSON をコピーできます)
重要な注意事項
- バッチ単位で検証する — 各バッチの収集後に、すべての入力を検証します
- 開始/終了ブロックの計算時には、 RPC から現在のブロック番号を取得します
- Q96 値を正しく計算する — 下限価格とティック間隔について:
- 重要: 小数点以下の桁数の違いを考慮します:
Q96 * ratio / 10^(tokenDecimals - currencyDecimals) - USDC はすべてのネットワークで小数点以下 6 桁です。小数点以下 18 桁のトークンの場合は 10^12 で割ります
- ネイティブ ETH は小数点以下 18 桁です。小数点以下 18 桁のトークンの場合、調整は不要です
- 重要: 小数点以下の桁数の違いを考慮します:
- 下限価格を丸めて、ティック間隔で割り切れるようにする:
roundedFloorPrice = (floorPrice // tickSpacing) * tickSpacing- 必ず確認すること:
roundedFloorPrice % tickSpacing == 0
- 供給スケジュールの生成には MCP ツールを使用する(起動していない場合はセットアップ手順を提示します)
- やり取りの回数を最小限にする — 1 回のバッチで、可能な限り多くのパラメーターを収集します
ネットワーク固有の定数
すぐ参照できるように保存します。
const NETWORKS = {
1: {
name: 'Mainnet',
blockTime: 12,
rpc: 'https://ethereum-rpc.publicnode.com',
usdc: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
},
130: {
name: 'Unichain',
blockTime: 1,
rpc: 'https://mainnet.unichain.org',
usdc: '0x078D782b760474a361dDA0AF3839290b0EF57AD6',
},
1301: {
name: 'Unichain Sepolia (Testnet)',
blockTime: 2,
rpc: 'https://sepolia.unichain.org',
usdc: '0x078D782b760474a361dDA0AF3839290b0EF57AD6',
},
8453: {
name: 'Base',
blockTime: 2,
rpc: 'https://mainnet.base.org',
usdc: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
},
42161: {
name: 'Arbitrum',
blockTime: 2,
rpc: 'https://arb1.arbitrum.io/rpc',
usdc: '0xaf88d065e77c8cc2239327c5edb3a432268e5831',
},
11155111: {
name: 'Sepolia',
blockTime: 12,
rpc: 'https://ethereum-sepolia-rpc.publicnode.com',
usdc: '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238',
},
};
// Q96 = 2^96 (JavaScript BigInt notation)
const Q96 = 79228162514264337593543950336n;
Python での同等の設定:
# Q96 = 2**96
Q96 = 79228162514264337593543950336
概要
CCA(Continuous Clearing Auction)は、一様価格オークションを連続時間に一般化した新しいオークション方式です。タイミングをめぐる駆け引きをなくし、早期参加を促しながら、初期流動性の立ち上げに向けた公正な価格発見を実現します。
主な機能:
- 公正な価格発見:タイミングをめぐる駆け引きのない連続清算
- 透明性の高い分配:あらかじめ定められたスケジュールに従って供給を放出
- 柔軟な設定:オークションのパラメーターとスケジュールをカスタマイズ可能
- マルチチェーン対応:EVM チェーン全体への標準デプロイ
- ファクトリーによるデプロイ:CREATE2 による一貫したアドレス
クイックガイド
| タスク... | 使用するセクション |
|---|---|
| オークションのパラメーターを設定する | 設定ガイド |
| 供給スケジュールを生成する | 供給スケジュールの設定 |
| オークションの仕組みを理解する | 技術概要 |
設定ガイド
オークションのパラメーター
CCA オークションは、AuctionParameters 構造体で設定します。
struct AuctionParameters {
address currency; // Token to raise funds in (address(0) for ETH)
address tokensRecipient; // Address to receive leftover tokens
address fundsRecipient; // Address to receive all raised funds
uint64 startBlock; // Block when auction starts
uint64 endBlock; // Block when auction ends
uint64 claimBlock; // Block when tokens can be claimed
uint256 tickSpacing; // Fixed granularity for prices (Q96)
address validationHook; // Optional hook (use 0x0 if none)
uint256 floorPrice; // Starting floor price (Q96)
uint128 requiredCurrencyRaised; // Minimum funds to graduate
bytes auctionStepsData; // Packed supply issuance schedule
}
設定ファイルの形式
JSON 設定ファイル(例:script/auction-config.json)を作成します。
{
"1": {
"token": "0x...",
"totalSupply": 1e29,
"currency": "0x0000000000000000000000000000000000000000",
"tokensRecipient": "0x...",
"fundsRecipient": "0x...",
"startBlock": 24321000,
"endBlock": 24327001,
"claimBlock": 24327001,
"tickSpacing": 79228162514264337593543950,
"validationHook": "0x0000000000000000000000000000000000000000",
"floorPrice": 7922816251426433759354395000,
"requiredCurrencyRaised": 0,
"supplySchedule": [
{ "mps": 1000, "blockDelta": 6000 },
{ "mps": 4000000, "blockDelta": 1 }
]
}
}
パラメーターの詳細
基本設定
| パラメーター | 型 | 説明 |
|---|---|---|
token | address | オークションにかけるトークン |
totalSupply | number | オークションにかけるトークンの総量(wei/最小単位) |
currency | address | 購入に使用するトークン(USDC など)、または ETH の場合は address(0) |
tokensRecipient | address | 売れ残ったトークンの送付先 |
fundsRecipient | address | 調達した資金の送付先 |
ブロック設定
| パラメーター | 型 | 説明 | 制約 |
|---|---|---|---|
startBlock | number | オークションの開始時点 | startBlock < endBlock |
endBlock | number | オークションの終了時点 | endBlock <= claimBlock |
claimBlock | number | トークンを請求できる時点 | claimBlock >= endBlock |
ネットワークごとのブロック時間:
- Mainnet、Sepolia:1 ブロックあたり 12 秒
- Unichain、Base、Arbitrum:1 ブロックあたり 2 秒
価格設定パラメーター
| パラメーター | 型 | 説明 |
|---|---|---|
floorPrice | number | 最低価格(Q96 形式) |
tickSpacing | number | 価格ティックの増分(Q96 形式) |
validationHook | address | 任意の検証コントラクト(指定しない場合は 0x0 を使用) |
requiredCurrencyRaised | number | 必要な最低調達額(最低額を設定しない場合は 0) |
供給スケジュール
| パラメーター | 型 | 説明 |
|---|---|---|
supplySchedule | array | {mps, blockDelta} オブジェクトの配列 |
価格の計算(Q96 形式)
CCA では、価格を高精度で計算するために Q96 固定小数点形式を使用します。基準値 2^96(79228162514264337593543950336)は、1:1 の価格比を表します。
最低価格の計算
重要:トークンと通貨の小数桁数の違いを考慮してください。
# Base value for 1:1 ratio
Q96 = 79228162514264337593543950336
# Formula: Q96 * (human price ratio) / 10^(token_decimals - currency_decimals)
# Example 1: USDC (6 decimals) per 18-decimal token at $0.10 ratio
token_decimals = 18
currency_decimals = 6 # USDC has 6 decimals
decimal_adjustment = 10 ** (token_decimals - currency_decimals) # 10^12
floorPrice = Q96 * 0.1 / decimal_adjustment
# Result: 7922816251426433759354395 (approximately)
# Example 2: Native ETH (18 decimals) per 18-decimal token at 0.1 ratio
token_decimals = 18
currency_decimals = 18 # Native ETH has 18 decimals
decimal_adjustment = 10 ** (18 - 18) # 10^0 = 1
floorPrice = Q96 * 0.1 / 1
# Result: 7922816251426433759354395034
重要なポイント: USDC はすべてのネットワークで小数桁数が 6 桁です。そのため、USDC と小数桁数が 18 桁のトークンを使用する場合は、10^12 で割る必要があります。
ティック幅の計算
ティック幅は、入札を配置できる価格を決定します。最低でも最低価格の 1 ベーシスポイントを選択してください。 1% または 10% も妥当です。
# Example: 1% of floor price
tickSpacing = int(floorPrice * 0.01)
# For floorPrice = 7922816251426433759354395000
# Result: 79228162514264337593543950
下限価格の丸め(重大)
下限価格はティック間隔で割り切れる必要があります。 正確に割り切れるように切り捨てます。
# Calculate tick spacing first
tickSpacing = int(floorPrice * 0.01) # 1% of floor price
# Round floor price DOWN to be evenly divisible
roundedFloorPrice = (floorPrice // tickSpacing) * tickSpacing
# VERIFY divisibility (must be True)
assert roundedFloorPrice % tickSpacing == 0, "Floor price must be divisible by tick spacing!"
例:
Q96 = 79228162514264337593543950336
raw_floor_price = int(Q96 * 0.0001) # 0.0001 ETH per token
# Result: 7922816251426434139029504
tick_spacing = int(raw_floor_price * 0.01) # 1%
# Result: 79228162514264350785536
rounded_floor_price = (raw_floor_price // tick_spacing) * tick_spacing
# Result: 7843588088912170727768064
# Verify: 7843588088912170727768064 / 79228162514264350785536 = 99 (exact)
# Remainder: 0 ✓
警告:ティック間隔を小さく設定しすぎると、オークションのガス効率が極端に悪くなり、DoS 攻撃につながる可能性があります。
供給スケジュールの設定
MPS(ミリベーシスポイント)について
供給スケジュールでは MPS = 1e7(1,000 万)を使用します。各単位は 1 ベーシスポイントの 1000 分の 1 を表します。
供給スケジュールは、時間の経過に伴うトークン発行率を定義します。各ステップには次の値が含まれます。
mps:ブロックごとにリリースされるトークン数(mps 単位)blockDelta:このレートが適用されるブロック数
標準スケジュール生成ツール
このプラグインには、次の特性を持つ正規化された凸曲線を使用して供給スケジュールを生成する MCP サーバーが含まれています。
- 12 ステップ(デフォルト、変更可能)で段階的にリリース
- ステップごとのトークン量は均等(段階的リリースが 70% の場合は 5.8333%)
- ブロック期間は減少(凸曲線の特性)
- 最終ブロックには残りのトークン(約 30%、変更可能な範囲は 20~40%)が割り当てられます
- 合計:リリースされる供給量は、各ステップについて
sum(mps * blockDelta)を計算した値が常にちょうど 10,000,000 MPS になります。mpsはブロックごとのリリース率であり、ステップごとの量ではないため、mps列だけを合計しても 10,000,000 にはなりません。
generate_supply_schedule MCP ツールを使用して、この標準分布を生成します。
MCP ツールの呼び出し:
{
"auction_blocks": 86400,
"prebid_blocks": 0
}
このアルゴリズムでは、次の値が自動的に計算されます。
- ステップごとの均等なトークン量(例:段階的リリースが 70% の場合、12 ステップでそれぞれ 5.8333%)
- 正規化曲線 C(t) = t^α(デフォルト α = 1.2)に基づく時間境界
- 時間とともに減少するブロック期間(凸曲線の特性)
sum(mps * blockDelta)がちょうど 10,000,000 MPS になるようにする最終ブロックの調整
例:Base での 2 日間のオークション
Base は 2 秒間隔でブロックを生成するため、2 日間は 86400 ブロックです。
generate_supply_schedule を次のように呼び出します。
{
"auction_blocks": 86400,
"prebid_blocks": 0
}
出力(正規化された凸分布):
{
"schedule": [
{ "mps": 54, "blockDelta": 10894 },
{ "mps": 68, "blockDelta": 8517 },
{ "mps": 75, "blockDelta": 7803 },
{ "mps": 79, "blockDelta": 7373 },
{ "mps": 83, "blockDelta": 7068 },
{ "mps": 85, "blockDelta": 6835 },
{ "mps": 88, "blockDelta": 6647 },
{ "mps": 90, "blockDelta": 6490 },
{ "mps": 92, "blockDelta": 6356 },
{ "mps": 94, "blockDelta": 6238 },
{ "mps": 95, "blockDelta": 6136 },
{ "mps": 97, "blockDelta": 6043 },
{ "mps": 2988006, "blockDelta": 1 }
],
"auction_blocks": 86400,
"prebid_blocks": 0,
"total_phases": 13,
"summary": {
"total_mps": 10000000,
"target_mps": 10000000,
"final_block_mps": 2988006,
"final_block_percentage": 29.88,
"num_steps": 12,
"alpha": 1.2,
"main_supply_pct": 70.0,
"step_tokens_pct": 5.8333
}
}
注:
- ブロック期間は減少します:10894 → 8517 → 7803 → ... → 6043
- ステップごとのトークン量はおおむね均等です(それぞれ約 5.8333%)
- 最終ブロックには全トークンの 29.88% が含まれます
sum(mps * blockDelta)はちょうど 10,000,000 MPS です(mps列だけの合計はかなり小さくなります)
例:事前入札期間がある場合
トークンがリリースされない事前入札期間(mps=0)を追加します。事前入札期間はスケジュールの先頭に追加されます。
generate_supply_schedule を次のように呼び出します。
{
"auction_blocks": 86400,
"prebid_blocks": 43200
}
出力:
{
"schedule": [
{ "mps": 0, "blockDelta": 43200 },
{ "mps": 54, "blockDelta": 10894 },
{ "mps": 68, "blockDelta": 8517 },
...
{ "mps": 2988006, "blockDelta": 1 }
],
"auction_blocks": 86400,
"prebid_blocks": 43200,
"total_phases": 14,
"summary": {
"total_mps": 10000000,
"target_mps": 10000000,
"final_block_mps": 2988006,
"final_block_percentage": 29.88,
"num_steps": 12,
"alpha": 1.2,
"main_supply_pct": 70.0,
"step_tokens_pct": 5.8333
}
}
**注:**事前入札フェーズは mps: 0 として先頭に追加されるだけです。オークション部分では、引き続き同じ正規化された凸分布が使用されます。
カスタムスケジュール
独自の分布を設定する場合は、スケジュールを手動で定義します。
{
"supplySchedule": [
{ "mps": 100, "blockDelta": 5000 },
{ "mps": 200, "blockDelta": 5000 },
{ "mps": 500, "blockDelta": 4400 }
]
}
重要:価格操作を防ぐため、最終ブロックでは大量のトークン(通常 30% 以上)を販売する必要があります。
オンチェーンデプロイ用の供給スケジュールのエンコード
供給スケジュールを生成した後、オンチェーンの AuctionParameters 構造体用に bytes 形式へエンコードする必要があります。このエンコードでは、各 {mps, blockDelta} 要素を uint64 にまとめます。
エンコードアルゴリズム
供給スケジュールの各要素について、次の処理を行います。
- 次の値を含む uint64(64 ビット/8 バイト)を作成します。
- 最初の 24 ビット:
mps値(左側をパディング) - 次の 40 ビット:
blockDelta値(左側をパディング)
- 最初の 24 ビット:
encodePackedを使用してすべての uint64 をまとめます(バイト列を連結)0xプレフィックス付きの 16 進 bytes 文字列として返します
エンコード式
// Solidity equivalent
uint64 packed = (uint64(mps) << 40) | uint64(blockDelta);
bytes memory auctionStepsData = abi.encodePacked(packed1, packed2, ...);
値の制約
- mps:24 ビットに収まる必要があります(最大値:16,777,215)
- blockDelta:40 ビットに収まる必要があります(最大値:1,099,511,627,775)
MCP ツールの使用
供給スケジュールをエンコードするには、encode_supply_schedule MCP ツールを使用します。
入力:
{
"schedule": [
{ "mps": 0, "blockDelta": 43200 },
{ "mps": 54, "blockDelta": 10894 },
{ "mps": 68, "blockDelta": 8517 }
]
}
出力:
{
"encoded": "0x0000000000a8c00000003600002aa60000004400002145...",
"length_bytes": 112,
"num_elements": 14
}
手動エンコードの例(Python)
def encode_supply_schedule(schedule):
"""Encode supply schedule to bytes."""
encoded_bytes = b''
for item in schedule:
mps = item['mps']
block_delta = item['blockDelta']
# Validate bounds
assert mps < 2**24, f"mps {mps} exceeds 24-bit max"
assert block_delta < 2**40, f"blockDelta {block_delta} exceeds 40-bit max"
# Pack into uint64: mps (24 bits) << 40 | blockDelta (40 bits)
packed = (mps << 40) | block_delta
# Convert to 8 bytes (big-endian)
encoded_bytes += packed.to_bytes(8, byteorder='big')
return '0x' + encoded_bytes.hex()
# Example
schedule = [
{"mps": 0, "blockDelta": 43200},
{"mps": 54, "blockDelta": 10894}
]
encoded = encode_supply_schedule(schedule)
print(encoded) # 0x0000000000a8c00000003600002aa6
設定フローとの統合
コンフィギュレータースキルを使用する場合:
generate_supply_scheduleMCP ツールでスケジュールを生成しますencode_supply_scheduleMCP ツールでスケジュールをエンコードします- エンコードされたバイト列を最終的な設定出力に含めます
auctionStepsDataパラメーターとしてデプロイスクリプトに渡します
エンコードされたバイト列は、configData パラメーターの一部として Factory の initializeDistribution 関数に渡されます。
現在のブロック番号の取得
startBlock の設定に使用する現在のブロックを取得するには、パブリック RPC を使用します。
利用可能なパブリック RPC
| ネットワーク | RPC URL |
|---|---|
| Mainnet | https://ethereum-rpc.publicnode.com |
| Unichain | https://unichain-rpc.publicnode.com |
| Base | https://mainnet.base.org |
| Arbitrum | https://arb1.arbitrum.io/rpc |
| Sepolia | https://ethereum-sepolia-rpc.publicnode.com |
ブロック番号の取得
curl -X POST "https://mainnet.base.org" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "eth_blockNumber",
"params": [],
"id": 1
}'
レスポンス:
{
"jsonrpc": "2.0",
"id": 1,
"result": "0x123abc"
}
ブロック番号を得るには、16 進数を 10 進数に変換します。
検証ルール
設定を生成する前に、次の点を確認してください。
- ブロック制約:
startBlock < endBlock <= claimBlock - 有効なアドレス:すべてのアドレスが有効な Ethereum アドレス(0x + 40 桁の 16 進数)であること
- 負でない値:すべての数値が >= 0 であること
- フロア価格の整合性:フロア価格がティック間隔の倍数であること
- ティック間隔:フロア価格の少なくとも 1 ベーシスポイント(1%、10%を推奨)
- 供給スケジュール:最後のブロックで相当量のトークン(約 30%以上)が販売されること
- 総供給量の上限:最大 1e30 wei(18 桁の小数を持つ 1 兆トークン)
- FoT トークン不可:転送時手数料のあるトークンはサポートされていません
- 最小小数桁数:小数桁数が 6 未満のトークンは使用しないでください
追加リソース
- CCA リポジトリ:https://github.com/Uniswap/continuous-clearing-auction
- 技術ドキュメント:リポジトリ内の
docs/TechnicalDocumentation.mdを参照してください - デプロイガイド:リポジトリ内の
docs/DeploymentGuide.mdを参照してください - ホワイトペーパー:リポジトリ内の
docs/assets/whitepaper.pdfを参照してください - 監査:リポジトリ内の
docs/audits/README.mdを参照してください - Uniswap ドキュメント:https://docs.uniswap.org/contracts/liquidity-launchpad/CCA
- バグ報奨金:https://cantina.xyz/code/f9df94db-c7b1-434b-bb06-d1360abdd1be/overview