Beitrag
Teile dein Wissen.
+15
Sui Move Error - Transaktion kann nicht verarbeitet werden Keine gültigen Gasmünzen für die Transaktion gefunden
Wenn ich das mache:
//Zahlung von der Primärmünze trennen const [PaymentCoin] = tx.SplitCoins ( tx.object (PrimaryCoin.CoinObjectID), [tx.pure.u64 (erforderlicher Zahlungsbetrag)] );
//Verwende die Originalmünze für die Gaszahlung tx.setGasPayment ([{ ObjektID: PrimaryCoin.CoinObjectID, Version: PrimaryCoin.Version, verdauen: PrimaryCoin.digest }]);
tx.setGasBudget (10_000_000); Es beschwert sich darüber, dass veränderbare Objekte nicht mehr als eines in einer Transaktion vorkommen können. Wenn ich die Gaszahlung entferne, beschwert es sich: „Transaktion kann nicht verarbeitet werden Für die Transaktion wurden keine gültigen Gasmünzen gefunden.“. Meine Vertragsfunktion akzeptiert 0,01 Sui als Gegenleistung für eine NFT
- Sui
- Transaction Processing
- Move
Antworten
5Das passiert, weil du versuchst, dasselbe Münzobjekt (primaryCoin
) sowohl als Gaszahlung als auch als Eingabe dafür zu verwendensplitCoins
, was es zu einer veränderlichen Referenz macht, die in zwei verschiedenen Kontexten verwendet wird — und Sui erlaubt das aus Sicherheitsgründen und linearer Logik nicht (da Münzen lineare Objekte sind).
Meiner Meinung nach ist es so, dass man die Gaszahlung überhaupt nicht manuell festlegt. Lassen Sie einfach die Sui-Geldbörse/den Kunden automatisch eine geeignete Gasmünze auswählen. Verwenden Sie diese Option nur, setGasPayment
wenn Sie wirklich angeben müssen, mit welcher Münze Sie Benzin bezahlen können (z. B. Geldbörsen mit mehreren Münzen, spezielles Gasmanagement). Andernfalls vermeiden Sie es.
Versuche Folgendes:
// Split the primary coin to get a payment coin
const [paymentCoin] = tx.splitCoins(
tx.object(primaryCoin.coinObjectId),
[tx.pure.u64(requiredPaymentAmount)]
);
// Do your call that sends .01 SUI and gets an NFT
tx.moveCall({
target: `${packageId}::your_module::buy_nft`,
arguments: [
paymentCoin,
// other args...
],
});
// DO NOT set gas payment manually
// tx.setGasPayment(...) ← Remove this line
// Optional: set budget
tx.setGasBudget(10_000_000);
// Send the transaction
const result = await signer.signAndExecuteTransactionBlock({
transactionBlock: tx,
options: { showEffects: true },
});
Sui wird:
- Wählen Sie automatisch eine Gasmünze (es könnte dieselbe oder eine andere SUI-Münze in der Brieftasche sein).
- Gehen Sie
splitCoins
sicher damit um. - Verwenden Sie eineandere Münze(oder manchmal dieselbe, aber unter der Haube durch eine korrekte Objektversionierung sicher gehandhabt).
Wichtig: Solange dein Portemonnaie mindestens 1$ SUI hat, mit dem Benzin gedeckt werden kann, funktioniert das.
Sie stoßen auf eine allgemeine Sui Move-Transaktionsdesign-Einschränkungdasselbe Münzobjekt kann nicht sowohl als veränderbare Eingabe (z. B. zum Teilen oder Übertragen) als auch als Gasmünze in einer einzigen Transaktion verwendet werden.
Warum passiert das
- Wenn Sie tx.SplitCoins (tx.object (PrimaryCoin.CoinObjectID),...) verwenden, markieren Sie PrimaryCoin als veränderbare Eingabe.
- Wenn Sie es auch mit tx.setGasPayment (...) als Gascoin festlegen, sieht Sui, dass dasselbe Objekt in zwei Rollen verwendet wird, was nicht erlaubt ist.
- Wenn Sie die Gaszahlung entfernen, kann Sui keine gültige Gasmünze finden, daher der Fehler „Keine gültigen Gasmünzen für die Transaktion gefunden“.
Aus dem Kontext:
Status der Transaktionseffekte: Ungültige Verwendung des Werts. Veränderlich entliehene Werte erfordern eine eindeutige Verwendung. Unveränderlich geliehene Werte können nicht übernommen oder veränderlich geliehen werden. Übernommene Werte können nicht erneut verwendet werden. (Quelle)
Wie behebt man
Sie müssen eine andere Münze für Gas verwenden als die, die Sie teilen oder übertragen.
Die Lösung: Halten Sie mindestens zwei SUI-Münzen in Ihrer Brieftasche bereit. Verwende eine für die Zahlung (Aufteilen/Übertragen) und eine andere für Benzin.
Beispiel für einen Ablauf
- Wählen Sie zwei Münzen aus:
- PrimaryCoin (zur Zahlung)
- GasCoin (für Gas)
- Teilen und mit PrimaryCoin bezahlen:
const [paymentCoin] = tx.splitCoins(
tx.object(primaryCoin.coinObjectId),
[tx.pure.u64(requiredPaymentAmount)]
);
- Stellen Sie die Gaszahlung mit GasCoin ein:
tx.setGasPayment([{
objectId: gasCoin.coinObjectId,
version: gasCoin.version,
digest: gasCoin.digest
}]);
tx.setGasBudget(10_000_000);
Verwenden Sie nicht dasselbe Münzobjekt sowohl für die Zahlung als auch für das Benzin.
Meine Referenz
Der Fehler tritt auf, weil Sie versuchen, primaryCoin
dasOriginalobjekt(das während des splitCoins
Vorgangs verbraucht wird) als Gaszahlung zu verwenden. Nach dem Teilen der Münze wird die Version/der Digest der Originalmünze ungültig. Bei erneuter Referenz wird der Fehler „Veränderbare Objekte können nicht mehr als ein Objekt vorkommen“ ausgelöst.
primaryCoin
Um das Problem zu beheben, stellen Sie die Gaszahlung nicht manuell mithilfe des Pre-Split-Objekts ein. Und stellen Sie sicher, dass Ihr primaryCoin
Guthaben ausreicht, um beides abzudecken:
- Der Zahlungsbetrag (
requiredPaymentAmount
= 0,01 SUI) - Das Gasbudget (
10_000_000
= 0,01 SUI) → Benötigte Summe:≥ 0,02 SUI
Versuche es einfach
// Split payment from primary coin (leaves remaining balance in primaryCoin)
const [paymentCoin] = tx.splitCoins(
tx.object(primaryCoin.coinObjectId),
[tx.pure.u64(requiredPaymentAmount)]
);
// DO NOT setGasPayment manually - SDK auto-uses updated primaryCoin for gas
tx.setGasBudget(10_000_000); // Gas paid from primaryCoin's remaining balance
Probleme
Sie stoßen auf zwei Hauptprobleme:
1.Mutabilitätsfehler: Der Versuch, dasselbe Münzobjekt sowohl für die Gaszahlung als auch für die Transaktionseingabe zu verwenden, führt zu dem Fehler: „Veränderbare Objekte können nicht mehr als einmal in einer Transaktion vorkommen.“
2.Fehlende Gasmünze: Ohne eine gültige Gasmünze tritt der Fehler „Transaktion kann nicht verarbeitet werden: Für die Transaktion wurden keine gültigen Gasmünzen gefunden“ auf.
Lösung
Um diese Probleme zu lösen:
1.Teilen Sie die primäre Münze für die Bezahlung: Verwenden Sie diese Optiontx.splitCoins
, um eine neue Münze für den NFT-Kauf zu erstellen und sicherzustellen, dass sie von der Gaszahlung getrennt ist.
-
tx.setGasPayment
Stellen Sie eine separate Gasmünze ein: Weisen Sie der Gaszahlung mit einer anderen Münze zu. -
tx.setGasBudget
Gasbudget definieren: Legen Sie ein geeignetes Gasbudget fest mit.
Kode
// Step 1: Split the primary coin for payment
const [paymentCoin] = tx.splitCoins(
tx.object(primaryCoin.coinObjectId),
[tx.pure.u64(requiredPaymentAmount)]
);
// Step 2: Set a separate gas payment coin
const gasCoin = tx.object(gasCoinObjectId);
tx.setGasPayment([{
objectId: gasCoin.coinObjectId,
version: gasCoin.version,
digest: gasCoin.digest
}]);
// Step 3: Set the gas budget for the transaction
tx.setGasBudget(10_000_000);
AufSuiist ein einzelnes Münzobjekt veränderbar (sein Gleichgewicht ändert sich, wenn du es benutzt), und du kannst in einer Transaktion nicht zweimal auf dasselbe veränderbare Objekt verweisen — aus diesem Grund:
Du trennst dich von derselben PrimaryCoin
Und du verwendest es auch als Gaszahlung
→ Der Transaction Builder kennzeichnet dies als „veränderbares Objekt erscheint mehr als einmal“.
Warum passiert die Meldung „Keine gültigen Gasmünzen gefunden“, wenn Sie SetGasPayment entfernen
Wenn Sie keine Gasmünze angeben, wählt das Sui SDK automatisch eine Gasmünze aus Ihren eigenen Münzen aus, die noch nicht für die Transaktion verwendet wurde. Da Ihre Transaktion jedoch bereits die einzige Münze verbraucht, die Sie haben (über SplitCoins), ist keine zusätzliche Münze mehr übrig, um Benzin zu bezahlen.
So beheben Sie das Problem:
Sie benötigen zwei verschiedene Münzobjekte:
Münze A→ wird nur für Gas verwendet
Münze B→ aufgeteilt für deine .01 SUI Zahlung
Wenn Sie nur eine Münze in Ihrer Brieftasche haben, müssen Sie diese zunächst in einer vorläufigenTransaktion in zwei separate Münzobjekte aufteilen.
Der Schlüssel ist:
- Sui verhindert, dass ein einzelnes Münzobjekt gleichzeitig Gas und veränderbare Eingabe in derselben Transaktion ist, da es als dieselbe veränderbare Referenz behandelt wird.
- Aber in Move kannst du eine Münze gegen Bezahlung erhalten, ohne dass es dir egal ist, von welchem Objekt sie stammt — einschließlich einer Münze, die zuvor in derselben Transaktion von der Gasmünze getrennt wurde.
Das bedeutet, dass deine Move-Funktion nur die Zahlungsmünze akzeptieren sollte, nicht die ursprüngliche Münze, und du überlässt es dem Transaction Builder, sie aufzuteilen, bevor du sie übergibst.
move
module my_package::nft_market {
use sui::coin::{Self, Coin};
use sui::sui::{SUI};
use sui::object::{UID};
use sui::transfer;
use sui::tx_context::{Self, TxContext};
/// Simple function: take 0.01 SUI and give NFT
public entry fun buy_nft(
payment: Coin<SUI>, // User provides exactly 0.01 SUI
ctx: &mut TxContext
) {
let amount = coin::value(&payment);
let price = 10_000_000; // 0.01 SUI in MIST (1 SUI = 1_000_000_000 MIST)
assert!(amount == price, 0);
// Transfer the payment to the seller (hardcoded example)
transfer::transfer(payment, tx_context::sender(ctx));
// Mint NFT for buyer
let nft = NFT {
id: object::new(ctx),
name: b"Special NFT".to_vec(),
};
transfer::transfer(nft, tx_context::sender(ctx));
}
struct NFT has key, store {
id: UID,
name: vector<u8>,
}
}
Wie das Problem dadurch behebt wird
Wenn der Client die Transaktion erstellt:
1. Die Gasmünze (tx.gas) wird automatisch für Gas verwendet.
2. Vom Benzin getrennt, um einen neuen PaymentCoin zu erhalten:
js
const [paymentCoin] = tx.splitCoins(
tx.gas, // mutable reference to gas coin
[tx.pure.u64(requiredPaymentAmount)]
);
tx.moveCall({
target: `${packageId}::nft_market::buy_nft`,
arguments: [paymentCoin],
});
tx.setGasBudget(10_000_000);
3. Sui erlaubt das, weil:
tx.gas
ist das ObjektGaszahlung. -Der geteilte Ausgang(paymentCoin
) ist einneues Objekt.- Sie sind jetztverschiedene veränderbare Objektein derTransaktion.
✅ Vorteil: Du brauchst das Wallet nicht mehr, um vorher zwei separate Münzobjekte aufzubewahren — die Move-Funktion kümmert sich nur noch um die Zahlungsmünze, und der Kunde kann sie jederzeit von der Gasmünze trennen, bevor er anruft.
Weißt du die Antwort?
Bitte melde dich an und teile sie.
Sui is a Layer 1 protocol blockchain designed as the first internet-scale programmable blockchain platform.
Verdiene deinen Anteil an 1000 Sui
Sammle Reputationspunkte und erhalte Belohnungen für deine Hilfe beim Wachstum der Sui-Community.
- Warum benötigt BCS eine genaue Feldreihenfolge für die Deserialisierung, wenn Move-Strukturen benannte Felder haben?53
- Fehler bei der Überprüfung mehrerer Quellen“ in den Veröffentlichungen des Sui Move-Moduls — Automatisierte Fehlerbehebung43
- Sui-Transaktion schlägt fehl: Objekte sind für eine andere Transaktion reserviert36
- Wie interagieren Fähigkeitsbeschränkungen mit dynamischen Feldern in heterogenen Sammlungen?05
- Sui Move Error - Transaktion kann nicht verarbeitet werden Keine gültigen Gasmünzen für die Transaktion gefunden05