概要
合計手数料 = 基本手数料(5,000 lamports/署名、50%バーン)+ 優先手数料 (CU_price * CU_limit / 1M lamports、100%がvalidatorへ)。トランザクションが 成功・失敗にかかわらず請求されます。
手数料計算アルゴリズム
トランザクションの合計手数料は
calculate_fee_details
によって計算されます:
total_fee = base_fee + prioritization_fee
入力値はトランザクションメッセージ、現在のlamports_per_signature
(現在5,000)、およびコンピュートバジェットinstructionsから算出された優先手数料です。合計手数料は実行開始前に手数料支払者から差し引かれます。トランザクションが失敗した場合も手数料は請求されます。
基本手数料
基本手数料は、Ed25519署名検証およびプリコンパイル署名検証のコストをカバーします。トランザクション内のすべての署名が課金対象となり、Ed25519、Secp256k1、Secp256r1プリコンパイルプログラムによって検証される署名も含まれます。
calculate_signature_fee
関数は以下を計算します:
signature_count = num_transaction_signatures+ num_ed25519_signatures+ num_secp256k1_signatures+ num_secp256r1_signatures (if feature enabled)base_fee = signature_count * lamports_per_signature
num_transaction_signatures:トランザクションのEd25519署名の数 (通常は署名者1人につき1つ)。num_ed25519_signatures、num_secp256k1_signatures、num_secp256r1_signatures:対応するプリコンパイルプログラムによって検証される署名。lamports_per_signature:現在 5,000 lamports。
手数料の分配
基本手数料と優先手数料は異なる方法で分配されます。ランタイム内の
calculate_reward_and_burn_fee_details
関数は以下を計算します:
burn_amount = transaction_fee * 50 / 100validator_share = (transaction_fee - burn_amount) + priority_fee
- 基本手数料(transaction_fee):50%が
バーン
(流通供給量から削除)され、50%はブロック生成validatorに分配されます。バーンの割合は
DEFAULT_BURN_PERCENT = 50です。 - 優先手数料:SIMD-0096に基づき、100%がvalidatorに分配されます(バーンなし)。
トランザクションに対するvalidatorの合計報酬は以下のとおりです:
validator_reward = (base_fee / 2) + prioritization_fee
優先手数料
優先手数料は、トランザクションのスケジューリング優先度を高めるオプションの手数料です。コンピュートユニット(CU)は、ランタイムがトランザクション実行中に計測する計算の単位です。すべての操作(算術演算、メモリアクセス、システムコール)は一定数のCUを消費します。優先手数料を設定するには、トランザクションにコンピュートバジェットinstructionsを含めます(詳細は優先手数料の使い方ガイドを参照してください)。
優先手数料の計算式
get_prioritization_fee
関数は以下を計算します:
micro_lamport_fee = compute_unit_price * compute_unit_limitprioritization_fee = ceil(micro_lamport_fee / 1,000,000)
| 変数 | 説明 | デフォルト |
|---|---|---|
compute_unit_price | SetComputeUnitPriceで設定する、CUあたりのマイクロlamports | 0マイクロlamports |
compute_unit_limit | SetComputeUnitLimitで設定する、トランザクションが消費できる最大CU数 | instructionsごとのデフォルト値の合計 |
1,000,000 | マイクロlamportsからlamportsへの変換係数(MICRO_LAMPORTS_PER_LAMPORT) | -- |
v1トランザクションは手数料を直接設定する
この価格×上限の計算式は、レガシーおよびv0トランザクションに適用されます。v1フォーマットでは、 優先手数料はメッセージ設定に直接指定されるlamports単位の絶対合計額であり、 CUあたりの価格も乗算も丸めも行いません。
コンピュートユニット上限
コンピュートユニット上限は、トランザクションが消費できる最大CU数です。
SetComputeUnitLimit
instruction が含まれていない場合、デフォルト値はinstructionsの数と種類から計算されます(非ビルトインinstructionあたり200,000 CU、ビルトインあたり3,000 CU)。デフォルト計算の詳細についてはコンピュートバジェットを参照してください。
優先手数料は実際のCU使用量ではなく、要求されたCU上限に基づきます。 必要以上に高い上限を設定すると、未使用のコンピュートユニットに対しても料金が発生します。
コンピュートユニット価格
コンピュートユニット価格は、要求されたCUごとに支払うオプションのマイクロlamports額です。CU価格は優先手数料を直接決定します。CU価格を設定するには、トランザクションに
SetComputeUnitPrice
instructionを含めます。
デフォルトのCU価格は0であるため、デフォルトの優先手数料も0です。
リアルタイムのCU価格の見積もりについては、以下の優先手数料APIプロバイダーを参照してください。
トランザクションスケジューリングの優先度
スケジューラーは
calculate_priority_and_cost
関数を使用してトランザクションをランク付けします:
Priority = reward * 1,000,000 / (cost + 1)
- reward:validatorの手数料収入 = 優先手数料 + 基本手数料のバーンされない部分。
calculate_reward_for_transactionによって計算されます。 - cost:スケジューラーの 推定CUコスト (署名コスト + 書き込みロックコスト + instruction dataコスト + プログラム実行コスト + ロード済みアカウントデータサイズコスト)。詳細は コンピュートバジェットを参照してください。
- 1,000,000:コストが生のlamportsでrewardを上回ることが多いため、精度を保持するための乗数。
- +1:ゼロ除算を防ぐため。
この優先度によって、スケジューラーのバッファから実行のためにトランザクションがデキューされる順序が決まります。
例:CU上限とCU価格の設定
以下の例は、Solana SDKを使用してトランザクションにCU上限とCU価格を設定する方法を示しています。
| SDK | ソースコードリファレンス |
|---|---|
@solana/web3.js(TypeScript) | ComputeBudgetProgram |
solana-sdk(Rust) | ComputeBudgetInstruction |
const limitInstruction = ComputeBudgetProgram.setComputeUnitLimit({units: 300_000});const priceInstruction = ComputeBudgetProgram.setComputeUnitPrice({microLamports: 1});
import {LAMPORTS_PER_SOL,SystemProgram,Transaction,Keypair,Connection,ComputeBudgetProgram,sendAndConfirmTransaction} from "@solana/web3.js";const connection = new Connection("http://localhost:8899", "confirmed");const sender = Keypair.generate();const recipient = new Keypair();const airdropSignature = await connection.requestAirdrop(sender.publicKey,LAMPORTS_PER_SOL);await connection.confirmTransaction(airdropSignature, "confirmed");// Create compute budget instructionsconst limitInstruction = ComputeBudgetProgram.setComputeUnitLimit({units: 300_000});const priceInstruction = ComputeBudgetProgram.setComputeUnitPrice({microLamports: 1});const transferInstruction = SystemProgram.transfer({fromPubkey: sender.publicKey,toPubkey: recipient.publicKey,lamports: 0.01 * LAMPORTS_PER_SOL});// Add the compute budget and transfer instructions to a new transactionconst transaction = new Transaction().add(limitInstruction).add(priceInstruction).add(transferInstruction);const signature = await sendAndConfirmTransaction(connection, transaction, [sender]);console.log("Transaction Signature:", signature);
Is this page helpful?