
Prioritätsgebühren: So funktionieren Solanas Transaktionsgebühren
Inhaltsverzeichnis
Worum geht es in diesem Artikel?
Solana ist schnell. Doch selbst auf der schnellsten verfügbaren Blockchain wünschen sich Nutzer eine optimierte Verarbeitung wichtiger Transaktionen. Mit Prioritätsgebühren können sie ihre Transaktion in der Ausführungsreihenfolge ganz nach vorne setzen. Diese zusätzlichen, optionalen Gebühren lassen sich einer Transaktion hinzufügen.
Dieser Artikel gibt einen kurzen Einblick in die Feinheiten der Transaktionsverarbeitung auf Solana. Er behandelt Transaktionen, ihren Lebenszyklus und die Funktionsweise von Transaktionsgebühren. Anschließend geht es um Prioritätsgebühren, ihre programmatische Implementierung und Best Practices.
Transaktionen und ihr Lebenszyklus
Transaktionen dienen dazu, Solana-Programme aufzurufen und Zustandsänderungen vorzunehmen. Sie bestehen aus mehreren Anweisungen, also Vorgaben für einzelne Programmaufrufe. Diese teilen dem Validator mit, welche Aktionen er auf welchen Accounts ausführen soll und ob die erforderlichen Berechtigungen vorliegen.
Eine Transaktion auf Solana durchläuft üblicherweise folgenden Lebenszyklus:
- Der Nutzer hat ein klares Ziel für die gewünschte Aktion. Alice möchte beispielsweise 10 SOL an Bob senden
- Der Nutzer erstellt eine Transaktion für die gewünschte Aktion. Alice erstellt beispielsweise eine Transaktion mit einer Anweisung, 10 SOL von ihrem Account auf Bobs Account zu übertragen. Außerdem fügt Alice einen aktuellen Blockhash hinzu und signiert die Transaktion mit ihrem privaten Schlüssel
- Der Nutzer sendet die Transaktion an das Netzwerk. Anschließend erhält er Informationen darüber, ob die Transaktion erfolgreich hinzugefügt wurde. Alice sendet die Transaktion beispielsweise mit dem Commitment-Status bestätigt. Sobald die Transaktion bestätigt ist, erhält sie eine Transaktionssignatur. Alice kann diese Signatur in einem Block-Explorer wie Orb verwenden, um zu sehen, dass sie Bob erfolgreich 10 SOL gesendet hat. Ihr Account wurde mit 10 SOL belastet und Bobs Account wurden 10 SOL gutgeschrieben
Wenn Nutzer eine signierte Transaktion an das Netzwerk senden, verwenden sie einen RPC-Anbieter wie Helius. Die RPCs von Helius empfangen die Transaktion und prüfen den aktuellen Leader-Zeitplan. Auf Solana sind zu bestimmten Zeiten nur bestimmte Validatoren dafür zuständig, Einträge zum Ledger hinzuzufügen. Der Leader erzeugt einen Block für seinen aktuellen Slot und ist vier aufeinanderfolgenden Slots zugewiesen. Die signierte Transaktion wird an den aktuellen Leader und die nächsten beiden Leader gesendet.
Der aktuelle Leader validiert die signierte Transaktion und führt weitere Vorverarbeitungsschritte aus, bevor er ihre Ausführung plant. Anders als andere L1s wie Ethereum hat Solana keine globale Transaktionswarteschlange. Die meisten Validatoren nutzen die von Solana Labs bereitgestellte Scheduler-Implementierung. Validatoren mit dem Jito-Validator-Client verwenden dagegen einen Pseudo-Mempool, also MempoolStream, um Transaktionen zu ordnen. Der Standard-Scheduler arbeitet mit mehreren Threads. Jeder Thread verwaltet eine Warteschlange mit Transaktionen, die auf ihre Ausführung warten. Transaktionen werden anhand einer Kombination aus First-in-first-out (FIFO) und Prioritätsgebühren in Blöcke eingeordnet. Diese Reihenfolge ist grundsätzlich nicht deterministisch, da die Transaktionen den Ausführungs-Threads weitgehend zufällig zugewiesen werden.
Nach der Ausführung wird eine Transaktion über Turbine verbreitet. Die zugehörigen Gebühren werden entsprechend bezahlt.
So funktionieren Transaktionsgebühren auf Solana
Transaktionsgebühren sind kleine Beträge, die für die Verarbeitung von Transaktionen auf Solana anfallen. Der aktuelle Leader verarbeitet die über das Netzwerk gesendeten Transaktionen und erzeugt daraus Ledger-Einträge. Sobald die Transaktion als Teil des Zustands bestätigt ist, wird eine Gebühr zur Unterstützung des Wirtschaftsmodells von Solana entrichtet. Transaktionsgebühren kommen Solana grundlegend zugute. Sie:
- vergüten Validatoren
- reduzieren den belegten Netzwerkplatz, indem sie Echtzeitkosten für Transaktionen schaffen
- sichern die langfristige wirtschaftliche Stabilität des Netzwerks durch eine vom Protokoll eingezogene Mindestgebühr
Kurzfristig stützt sich Solana auf inflationsbasierte Protokollbelohnungen, um das Netzwerk zu sichern. Dafür gilt im gesamten Netzwerk eine planmäßige Inflationsrate, mit der Validatoren belohnt werden. Langfristig finanziert Solana die Sicherheit durch Transaktionsgebühren. Ein fester Anteil jeder Transaktionsgebühr (anfänglich auf 50 % festgelegt) wird verbrannt. Der Rest geht an den aktuellen Leader. Solana verbrennt Gebühren, um den Wert von SOL zu stärken und böswillige Validatoren davon abzuhalten, Transaktionen zu zensieren.
Transaktionsgebühren werden anhand einer statisch festgelegten Grundgebühr pro Signatur und der während der Transaktion verbrauchten Rechenressourcen berechnet, die in Compute Units (CU) gemessen werden. Diese Grundgebühr kann zwischen 50 % und 1000 % der angestrebten Lamports pro Signatur liegen. Der Standardzielwert pro Signatur liegt derzeit bei 10.000. Jede Transaktion erhält ein maximales CU-Budget, das sogenannte Compute Budget. Wird dieses Budget überschritten, stoppt die Runtime die Transaktion und gibt einen Fehler zurück. Das maximale Budget pro Transaktion beträgt 1,4 Millionen CU. Das Blockspace-Limit liegt bei 48 Millionen CU.
Was sind Prioritätsgebühren?
Aufgrund dieser Limits können rechenintensive Transaktionen den Blockspace füllen und andere Transaktionen verzögern. Deshalb hat Solana eine optionale Gebühr eingeführt, mit der Transaktionen gegenüber anderen Transaktionen in der Warteschlange des Leaders priorisiert werden können: die Prioritätsgebühr. Durch diese Gebühr rückst du deine Transaktion effektiv nach vorne und beschleunigst ihre Ausführung. Das ist besonders bei zeitkritischen oder hochwertigen Transaktionen nützlich. Die Gebührenpriorität einer Transaktion hängt von der Anzahl der angeforderten Compute Units ab. Je mehr Compute Units sie anfordert, desto höher muss die Gebühr sein, damit sie ihre Priorität in der Transaktionswarteschlange behält. Höhere Gebühren für mehr Compute Units verhindern Spam durch rechenintensive Transaktionen.
Prioritätsgebühren ergeben sich aus dem Compute Budget einer Transaktion multipliziert mit ihrem in Mikro-Lamports gemessenen Preis pro Compute Unit: priorityFees = computeBudget * computeUnitPrice
Compute Budget
Das computeBudget legt fest, wie viele Compute Units eine Transaktion maximal verbrauchen darf, welche Kosten mit den verschiedenen möglichen Operationen verbunden sind und welche Ausführungsgrenzen sie einhalten muss. Folgende Operationen verursachen Rechenkosten:
- Ausführen von SBF-Anweisungen
- Übertragen von Daten zwischen Programmen
- Aufrufen von Systemaufrufen (z. B. Protokollierung, Erstellen einer Programmadresse, CPIs)
Bei programmübergreifenden Aufrufen (CPIs) arbeitet das aufgerufene Programm innerhalb des Rechenbudgets des aufrufenden, also übergeordneten Programms. Verbraucht das aufgerufene Programm das gesamte verbleibende Rechenbudget oder überschreitet es ein festgelegtes Limit, schlägt die gesamte Kette der Programmaufrufe fehl. Das schließt die Ausführung der ursprünglichen Transaktion ein, die den Prozess gestartet hat.
Das aktuelle Compute Budget findest du hier.
Prioritätsgebühren programmatisch implementieren
Die Prioritätsgebühr einer Transaktion wird durch eine SetComputeUnitPrice-Anweisunghttps://github.com/solana-labs/solana/blob/2971e84ec87815adb1e4def95cbcd8d0d96845f5/sdk/src/compute_budget.rs#L59und eine optionale SetComputeUnitLimit-Anweisung festgelegt. Fehlt eine SetComputeUnitPrice-Anweisung, erhält die Transaktion standardmäßig die niedrigste Priorität, da keine zusätzliche Gebühr gezahlt wird. Fehlt eine SetComputeUnitLimit-Anweisung, wird das Limit aus der Anzahl der Anweisungen in der Transaktion multipliziert mit dem Standardlimit für Compute Units berechnet. Die Runtime berechnet die Prioritätsgebühr aus dem Preis pro Compute Unit und dem Compute-Unit-Limit. Anhand dieser Gebühr priorisiert sie die jeweilige Transaktion.
Um Prioritätsgebühren programmatisch hinzuzufügen, müssen wir diese Anweisungen in die gewünschte Transaktion aufnehmen. In JavaScript sieht das so aus:
import {
Keypair,
Connection,
PublicKey,
Transaction,
SystemProgram,
LAMPORTS_PER_SOL,
sendAndConfirmTransaction,
ComputeBudgetProgram,
} from "@solana/web3.js";
async function main() {
// Initialize an RPC client
const clusterUrl = "http://127.0.0.1:8899";
const connection = new Connection(clusterUrl, "confirmed");
// Initialize new sender and receiver keypairs
const fromKeypair = Keypair.generate();
const toPubkey = new PublicKey(Keypair.generate().publicKey);
// Airdrop SOL to the from_keypair
const airdropAmount = 100 * LAMPORTS_PER_SOL;
try {
const signature = await connection.requestAirdrop(
fromKeypair.publicKey,
airdropAmount
);
console.log("Airdrop requested. Signature:", signature);
await connection.confirmTransaction({
signature,
confirmation: "confirmed",
});
} catch (e) {
console.error("Failed to request airdrop:", e);
return;
}
// Check if airdrop was successful
const balance = await connection.getBalance(fromKeypair.publicKey);
if (balance < airdropAmount) {
console.error(
"Airdrop was not successful. The current balance is insufficient"
);
return;
}
// Airdrop SOL to the toPubkey
const airdropAmountTo = 100 * LAMPORTS_PER_SOL; // 1 SOL in lamports
try {
const signature = await connection.requestAirdrop(toPubkey, airdropAmount);
console.log("Airdrop requested. Signature:", signature);
await connection.confirmTransaction({
signature,
confirmation: "confirmed",
});
} catch (e) {
console.error("Failed to request airdrop:", e);
return;
}
// Check if airdrop was successful
const balanceTo = await connection.getBalance(toPubkey);
if (balance < airdropAmount) {
console.error(
"Airdrop was not successful. The current balance is insufficient"
);
return;
}
console.log(`Account balance: ${balance / LAMPORTS_PER_SOL} SOL`);
// Create the priority fee instructions
const computePriceIx = ComputeBudgetProgram.setComputeUnitPrice({
microLamports: 1,
});
const computeLimitIx = ComputeBudgetProgram.setComputeUnitLimit({
units: 200_000,
});
// Create the transfer instruction
const transferIx = SystemProgram.transfer({
fromPubkey: fromKeypair.publicKey,
toPubkey,
lamports: 100_000,
});
// Create the transaction with priority fees
const transaction = new Transaction().add(
computePriceIx,
computeLimitIx,
transferIx
);
// Fetch the recent blockhash and sign the transaction
transaction.recentBlockhash = (
await connection.getLatestBlockhash()
).blockhash;
transaction.sign(fromKeypair);
// Send the transaction
try {
const txid = await sendAndConfirmTransaction(connection, transaction, [
fromKeypair,
]);
console.log("Transaction sent successfully with signature", txid);
} catch (e) {
console.error("Failed to send transaction:", e);
}
}
main();In diesem Codeausschnitt führen wir folgende Schritte aus:
- Eine Testumgebung mit Localhost einrichten
- Zwei neue Wallets erstellen, nämlich
fromKeypairundtoPubkey - Per Airdrop jeweils 100 SOL an beide Wallets senden
- Prüfen, ob die Airdrops erfolgreich waren
- Die Anweisungen für die Prioritätsgebühr erstellen, nämlich
computePriceIxundcomputeLimitIx - Eine Übertragungsanweisung erstellen, die 100.000 Lamports von
fromKeypairantoPubkeysendet - Eine neue Transaktion erstellen und ihr alle Anweisungen hinzufügen
- Den neuesten Blockhash an die Transaktion anhängen und sie signieren
- Die Transaktion senden und ihre erfolgreiche Übermittlung bestätigen
Das war's – Prioritätsgebühren sind lediglich Anweisungen, die einer Transaktion hinzugefügt werden, um für eine schnellere Ausführung zu bezahlen. Der Großteil dieses Codeausschnitts konfiguriert unsere Entwicklungsumgebung und zwei Wallets, zwischen denen SOL übertragen werden. Uns interessiert vor allem, wie wir die Anweisungen für Prioritätsgebühren erstellen und einer Transaktion hinzufügen:
// Other code
const computePriceIx = ComputeBudgetProgram.setComputeUnitPrice({
microLamports: 1,
});
const computeLimitIx = ComputeBudgetProgram.setComputeUnitLimit({
units: 200_000,
});
// Other code
const transaction = new Transaction().add(computePriceIx, computeLimitIx, transferIx);
// Rest of the codeBest Practices
Die Reihenfolge dieser Anweisungen ist wichtig, da sie nacheinander ausgeführt werden. Wenn eine Transaktion beispielsweise das standardmäßige Rechenlimit von 200.000 CU überschreitet, bevor das Limit erhöht wird, schlägt sie fehl. Nehmen wir folgende Transaktion an:
- Anweisung 1 verbraucht 100.000 CU
- Anweisung 2 verbraucht 150.000 CU
- Anweisung 3 erhöht das Rechenlimit
Diese Transaktion schlägt fehl, wenn die Anweisungen 2 und 3 nicht vertauscht werden. Deshalb solltest du die Anweisung für das Rechenlimit vor allen anderen Anweisungen zur Transaktion hinzufügen. Denk daran: Du musst die SetComputeLimit-Anweisung nicht verwenden, wenn du deiner Transaktion Prioritätsgebühren hinzufügen möchtest – sie ist vollständig optional. Die Position der SetComputePrice-Anweisung spielt keine Rolle.
Wir empfehlen die RPC-Methode getRecentPrioritizationFees, um eine Liste kürzlich gezahlter Prioritätsgebühren abzurufen. Anhand dieser Daten kannst du eine angemessene Prioritätsgebühr für Transaktionen schätzen. So stellst du sicher, dass der Cluster sie verarbeitet, und minimierst gleichzeitig die gezahlten Gebühren. Alternativ bietet Helius eine neue Priority Fee API, die wir im nächsten Abschnitt behandeln.
Transaktionen sollten außerdem nur die Mindestanzahl an Compute Units anfordern, die für ihre Ausführung erforderlich ist. So bleiben die Gebühren möglichst niedrig. Beachte, dass die Kosten nicht angepasst werden, wenn die Anzahl der angeforderten Compute Units die tatsächlich von einer Transaktion verbrauchten Einheiten übersteigt.
Einige Wallet-Anbieter wie Phantom berücksichtigen, dass dApps Prioritätsgebühren für Transaktionen festlegen können. Sie raten jedoch davon ab, weil dies für Endnutzer häufig unnötige Komplexität schafft. Stattdessen empfehlen sie dApp-Entwicklern, Phantom die Prioritätsgebühren im Namen des Nutzers anwenden zu lassen. Solfare löst das Problem beispielsweise, indem es automatisch erkennt, ob Solana ausgelastet ist, und die Gebühren leicht erhöht, um deine Transaktion gegenüber anderen zu priorisieren.
Helius Priority Fee API
Prioritätsgebühren mit der RPC-Methode getRecentPrioritizationFees zu berechnen, ist für eine slotbasierte Berechnung intuitiv sinnvoll. Aufgrund der sich ständig ändernden Netzwerkbedingungen und der Art der Antwort von getRecentPrioritizationFees' kann dies jedoch schwierig sein. Die Methode gibt eine Liste mit Werten für die letzten 150 Blöcke zurück, die lediglich dabei hilft, den Mindestwert für die Gebühren abzuschätzen.
Die Helius Priority Fee API führt die neue Methode getPriorityFeeEstimate ein. Sie vereinfacht die Antwort auf einen einzelnen Wert und berücksichtigt dabei globale und lokale Gebührenmärkte. Die Methode ermittelt die Schätzung anhand vordefinierter Perzentile. Diese Perzentile oder Stufen reichen von NONE (0. Perzentil) bis UNSAFE_MAX (100. Perzentil, als unsicher gekennzeichnet, damit Nutzer nicht versehentlich ihr Guthaben aufbrauchen). Nutzer können außerdem alle Prioritätsstufen anfordern und über lookbackSlots den für die Berechnung verwendeten Bereich anpassen. Ähnlich wie bei getRecentPrioritizationFees können Nutzer für die Schätzung somit eine bestimmte Anzahl vergangener Slots berücksichtigen.
Mit dem folgenden Skript können wir beispielsweise alle Prioritätsgebührenstufen für das Jupiter-v6-Programm berechnen:
const url = `https://mainnet.helius-rpc.com/?api-key=`;
const getRecentPrioritizationFees = async () => {
const response = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
jsonrpc: "2.0",
id: 1,
method: "getPriorityFeeEstimate",
params: [{
"accountKeys": ["JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4"],
"options": {
"includeAllPriorityFeeLevels": true,
}
}]
}),
});
const data = await response.json();
console.log("Fee: ", data);
};
getRecentPrioritizationFees();Dieser Endpunkt wird aktiv weiterentwickelt. Weitere Informationen findest du in der Helius-Dokumentation.
Fazit
Ein Blick auf Solana-Transaktionen zeigt ein ausgefeiltes System, das Netzwerkeffizienz und wirtschaftliche Anreize ausbalanciert. Wenn Entwickler und Nutzer verstehen, wie Transaktionen, Transaktionsgebühren und Prioritätsgebühren funktionieren, können sie fundiertere Entscheidungen treffen und ihre Interaktionen mit Solana optimieren. Die programmatische Implementierung von Prioritätsgebühren eröffnet neue Möglichkeiten für hochwertige und zeitkritische Transaktionen. Dadurch werden Abläufe auf Solana flexibler und effizienter.
Wenn du bis hierhin gelesen hast: Vielen Dank, Anon! Gib unten deine E-Mail-Adresse ein, damit du keine Neuigkeiten zu Solana verpasst. Möchtest du tiefer einsteigen? Tritt unserem Discord bei und beginne noch heute damit, die Zukunft auf der leistungsfähigsten Blockchain zu entwickeln.
Zusätzliche Ressourcen und weiterführende Literatur
Ähnliche Artikel
Helius abonnieren
Bleib bei der Solana-Entwicklung auf dem Laufenden und erhalte Updates, wenn wir neue Beiträge veröffentlichen


