Podsumowanie
Całkowita opłata = opłata podstawowa (5 000 lamportów/podpis, 50% spalane) + opłata priorytetowa (CU_price * CU_limit / 1M lamportów, 100% dla validatora). Pobierana niezależnie od tego, czy transakcja zakończy się sukcesem, czy nie.
Algorytm obliczania opłat
Całkowita opłata za transakcję jest obliczana przez
calculate_fee_details:
total_fee = base_fee + prioritization_fee
Dane wejściowe to komunikat transakcji, aktualny lamports_per_signature
(obecnie 5 000) oraz opłata priorytetowa wyliczona na podstawie instrukcji
compute budget. Całkowita opłata jest pobierana od płatnika opłaty przed
rozpoczęciem wykonania. Jeśli transakcja się nie powiedzie, opłata i tak jest
pobierana.
Opłata podstawowa
Opłata podstawowa pokrywa koszt weryfikacji podpisu Ed25519 oraz wszelkich weryfikacji podpisów przez prekompilowane programy. Każdy podpis w transakcji jest obciążany opłatą, w tym podpisy weryfikowane przez programy prekompilowane Ed25519, Secp256k1 i Secp256r1.
Funkcja
calculate_signature_fee
oblicza:
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: liczba podpisów Ed25519 w transakcji (zwykle jeden na sygnatariusza).num_ed25519_signatures,num_secp256k1_signatures,num_secp256r1_signatures: podpisy weryfikowane przez odpowiednie prekompilowane programy.lamports_per_signature: obecnie 5 000 lamportów.
Podział opłat
Opłata podstawowa i opłata priorytetowa są rozdzielane w różny sposób. Funkcja
calculate_reward_and_burn_fee_details
w runtime oblicza:
burn_amount = transaction_fee * 50 / 100validator_share = (transaction_fee - burn_amount) + priority_fee
- Opłata podstawowa (transaction_fee): 50% jest
spalane
(usuwane z obiegu), a 50% trafia do validatora produkującego blok. Procent
spalania to
DEFAULT_BURN_PERCENT = 50. - Opłata priorytetowa: 100% trafia do validatora (nic nie jest spalane), zgodnie z SIMD-0096.
Całkowita nagroda validatora za transakcję to:
validator_reward = (base_fee / 2) + prioritization_fee
Opłata za priorytet
Opłata za priorytet to opcjonalna opłata, która zwiększa priorytet realizacji transakcji. Jednostka obliczeniowa (CU) to jednostka obliczeń, którą środowisko wykonawcze mierzy podczas realizacji transakcji. Każda operacja (arytmetyczna, dostęp do pamięci, syscall) kosztuje określoną liczbę CU. Możesz ustawić opłatę za priorytet, dodając instrukcje budżetu obliczeniowego do swojej transakcji. (Szczegóły znajdziesz w przewodniku Jak korzystać z opłat priorytetowych.)
Wzór na opłatę za priorytet
Funkcja
get_prioritization_fee
oblicza:
micro_lamport_fee = compute_unit_price * compute_unit_limitprioritization_fee = ceil(micro_lamport_fee / 1,000,000)
| Zmienna | Opis | Domyślna wartość |
|---|---|---|
compute_unit_price | Mikro-lamporty za CU, ustawiane przez SetComputeUnitPrice | 0 mikro-lamportów |
compute_unit_limit | Maksymalna liczba CU, jaką może zużyć transakcja, ustawiana przez SetComputeUnitLimit | Suma wartości domyślnych dla instrukcji |
1,000,000 | Współczynnik konwersji z mikro-lamportów na lamporty (MICRO_LAMPORTS_PER_LAMPORT) | -- |
Limit jednostek obliczeniowych
Limit jednostek obliczeniowych to maksymalna liczba CU, jaką może zużyć
transakcja. Jeśli nie zostanie dodana instrukcja
SetComputeUnitLimit,
domyślna wartość jest wyliczana na podstawie liczby i typu instrukcji (200 000
CU na każdą nie-wbudowaną instrukcję, 3 000 na każdą wbudowaną). Szczegóły
dotyczące domyślnego wyliczania znajdziesz w
Compute Budget.
Opłata za priorytet jest oparta na zadeklarowanym limicie CU, a nie na faktycznym zużyciu CU. Ustawienie wyższego limitu niż potrzebny oznacza płacenie za niewykorzystane jednostki obliczeniowe.
Cena jednostki obliczeniowej
Cena jednostki obliczeniowej to opcjonalna kwota mikro-lamportów płacona za
każdą zadeklarowaną CU. Cena CU bezpośrednio określa wysokość opłaty za
priorytet. Aby ustawić cenę CU, dodaj do transakcji instrukcję
SetComputeUnitPrice.
Domyślna cena CU to 0, co oznacza, że domyślna opłata za priorytet również wynosi 0.
Aby uzyskać szacunkowe ceny CU w czasie rzeczywistym, zobacz poniżej dostawców API opłat priorytetowych.
| Dostawca | API opłat priorytetowych |
|---|---|
| Helius | Dokumentacja |
| QuickNode | Dokumentacja |
| Triton | Dokumentacja |
Priorytet harmonogramowania transakcji
Scheduler ustala kolejność transakcji za pomocą funkcji
calculate_priority_and_cost:
Priority = reward * 1,000,000 / (cost + 1)
- reward: dochód validatora z opłat = opłata za priorytet + nieprzepalona
część opłaty bazowej. Obliczane przez
calculate_reward_for_transaction. - cost: szacowany koszt CU przez scheduler (koszty podpisu + koszty write lock + koszty instruction data + koszty wykonania programu + koszt rozmiaru załadowanych danych kont). Szczegóły znajdziesz w sekcji Compute Budget.
- 1 000 000: mnożnik dla zachowania precyzji, ponieważ koszt często przekracza reward w surowych lamportach.
- +1: zapobiega dzieleniu przez zero.
Priorytet decyduje o kolejności, w jakiej transakcje są pobierane z bufora schedulera do wykonania.
Przykład: Ustawianie limitu CU i ceny CU
Poniższe przykłady pokazują, jak ustawić limit CU i cenę CU w transakcji przy użyciu SDK Solana.
| SDK | Odnośnik do kodu źródłowego |
|---|---|
@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?