Beitrag
Teile dein Wissen.
Münze 2 mal an dieselbe Adresse prägen
Wenn ich meine Münze zweimal an dieselbe Adresse präge, summieren sich die Beträge nicht. Im Test taucht nur der letzte Münzbetrag auf?
module package_addr::my_coin;
//https://docs.sui.io/guides/developer/coin
use sui::coin::{Self, Coin, TreasuryCap, CoinMetadata};
public struct MY_COIN has drop {}
const TOTAL_SUPPLY: u64 = 1_000_000_000_000_000_000;//includes decimal zeros
const INITIAL_SUPPLY: u64 = 900_000_000_000_000_000;
const REMAINING: u64 =
100_000_000_000_000_000;
fun init(witness: MY_COIN, ctx: &mut TxContext) {
let (mut treasury, metadata) = coin::create_currency(
witness,
9,
b"MY_COIN",
b"",
b"",
option::none(),
ctx,
);
mint( &mut treasury, INITIAL_SUPPLY, ctx.sender(), ctx);
transfer::public_freeze_object(metadata);
transfer::public_transfer(treasury, ctx.sender())
}
public fun mint(
treasury_cap: &mut TreasuryCap<MY_COIN>,
amount: u64,
recipient: address,
ctx: &mut TxContext,
) {
let coin = coin::mint(treasury_cap, amount, ctx);
transfer::public_transfer(coin, recipient)
}
//----------== Test
#[test_only]use sui::test_scenario;
#[test_only] use sui::coin::value;
#[test_only] use std::debug::print as pp;
#[test_only] use std::string::{utf8};
#[test]
fun test_init() {
let admin = @0xAd;
let bob = @0xb0;
let mut sce = test_scenario::begin(admin);
{
let otw = MY_COIN{};
init(otw, sce.ctx());
};
sce.next_tx(admin);
{
let coin = sce.take_from_sender<Coin<MY_COIN>>();
pp(&utf8(b"admin balc1"));
pp(&value(&coin));
assert!(value(&coin) == INITIAL_SUPPLY, 441);
sce.return_to_sender(coin);
};
//mint 2nd time
sce.next_tx(admin);
{
let mut treasury = sce.take_from_sender<TreasuryCap<MY_COIN>>();
mint(
&mut treasury,
2000,
admin,//sce.ctx().sender(),
sce.ctx()
);
sce.return_to_sender(treasury);
};
sce.next_tx(admin);
{
let coin = sce.take_from_sender<Coin<MY_COIN>>();
pp(&utf8(b"admin balc2"));
pp(&value(&coin));// it shows 2000, instead of INITIAL_SUPPLY+2000 !!??
assert!(value(&coin) == INITIAL_SUPPLY+2000, 442);// Failed here
sce.return_to_sender(coin);
};
sce.end();
}
- Sui
- SDKs and Developer Tools
Antworten
2Das Problem ist, dass es sich um unterschiedliche Coin
Objekte handelt. In Sui Move erstellt jeder Mint-Vorgang ein neues <T>
Coin-Objekt, anstatt es automatisch mit vorhandenen Münzen desselben Typs zu kombinieren.
Du musst also eine weitere Scheintransaktion erstellen, um beide Coin-Objekte zu erhalten und sie miteinander zu verbinden... siehe unten
module package_addr::my_coin;
//https://docs.sui.io/guides/developer/coin
use sui::coin::{Self, Coin, TreasuryCap, CoinMetadata};
public struct MY_COIN has drop {}
const TOTAL_SUPPLY: u64 = 1_000_000_000_000_000_000;//includes decimal zeros
const INITIAL_SUPPLY: u64 = 900_000_000_000_000_000;
const REMAINING: u64 =
100_000_000_000_000_000;
fun init(witness: MY_COIN, ctx: &mut TxContext) {
let (mut treasury, metadata) = coin::create_currency(
witness,
9,
b"MY_COIN",
b"",
b"",
option::none(),
ctx,
);
mint( &mut treasury, INITIAL_SUPPLY, ctx.sender(), ctx);
transfer::public_freeze_object(metadata);
transfer::public_transfer(treasury, ctx.sender())
}
public fun mint(
treasury_cap: &mut TreasuryCap<MY_COIN>,
amount: u64,
recipient: address,
ctx: &mut TxContext,
) {
let coin = coin::mint(treasury_cap, amount, ctx);
transfer::public_transfer(coin, recipient)
}
//----------== Test
#[test_only]use sui::test_scenario;
#[test_only] use sui::coin::value;
#[test_only] use std::debug::print as pp;
#[test_only] use std::string::{utf8};
#[test]
fun test_init() {
let admin = @0xAd;
let mut sce = test_scenario::begin(admin);
{
let otw = MY_COIN{};
init(otw, sce.ctx());
};
// First transaction - check initial supply
sce.next_tx(admin);
{
let coin = sce.take_from_sender<Coin<MY_COIN>>();
pp(&utf8(b"admin balc1"));
pp(&value(&coin));
assert!(value(&coin) == INITIAL_SUPPLY, 441);
sce.return_to_sender(coin);
};
// Second transaction - mint additional coins
sce.next_tx(admin);
{
let mut treasury = sce.take_from_sender<TreasuryCap<MY_COIN>>();
mint(
&mut treasury,
2000,
admin,
sce.ctx()
);
sce.return_to_sender(treasury);
};
// Third transaction - check combined balance
sce.next_tx(admin);
{
// Take both coins from sender
let coin1 = sce.take_from_sender<Coin<MY_COIN>>(); // Initial coin
let coin2 = sce.take_from_sender<Coin<MY_COIN>>(); // Newly minted coin
// Combine them
let mut combined_coin = coin1;
coin::join(&mut combined_coin, coin2);
pp(&utf8(b"admin balc2"));
pp(&value(&combined_coin));
assert!(value(&combined_coin) == INITIAL_SUPPLY + 2000, 442);
sce.return_to_sender(combined_coin);
};
sce.end();
}
Die wichtigsten Punkte:
Bei der ersten Transaktion überweisen wir die ursprüngliche Münze zurück an den Absender, anstatt sie zurückzugeben
Bei der zweiten Transaktion prägen wir neue Münzen, wodurch ein separates Coin-Objekt entsteht
In der dritten Transaktion nehmen wir beide Münzen vom Absender
Benutze coin: :join, um sie zu kombinieren
Überprüfen Sie den Gesamtwert
Dies entspricht dem echten Verhalten von Sui, bei dem jede Münzprägung ein neues Coin-Objekt erstellt
Geldbörsen kombinieren Münzen in der Regel automatisch
Du musst Coins in Tests explizit zusammenführen, da das Testszenario sie nicht automatisch kombiniert.
Wenn Sie Ihre benutzerdefinierte Münze mehrmals an dieselbe Adresse auf Sui prägen, erstellt jede Prägeanstalt ein separates Coin<T>
Objekt, anstatt das vorhandene Objekt zu ergänzen. Wenn du also das Guthaben mit nur einem Münzobjekt überprüfst, siehst du nur den Wert dieser einzelnen Münze, normalerweise der letzten, die geprägt wurde. Um das volle Guthaben zu erhalten, müssen Sie alle Münzobjekte zusammenführen, die zu Ihrer Adresse gehören. Coin<MY_COIN>
In Tests bedeutet das, dass du dir jedes Objekt schnappst, coin::merge
das der Absender besitzt, und sie miteinander kombinierst. Ohne dies zu tun, zeigt der Test nur den Betrag einer Münze an, nicht die Summe aller geprägten Münzen. Hier ist ein einfaches Beispiel dafür, wie zwei Münzen nach mehreren Prägungen in einem Transaktionsblock zusammengeführt werden:
let coin1 = sce.take_from_sender<Coin<MY_COIN>>();
let coin2 = sce.take_from_sender<Coin<MY_COIN>>();
let merged_coin = coin::merge(coin1, coin2);
pp(&value(&merged_coin));
Wenn Sie mehrere Münzen an dieselbe Adresse geprägt haben, stellen Sie immer sicher, dass Sie sie zusammenführen, bevor Sie das Guthaben ablesen oder die Münzen für andere Operationen verwenden. Hier erfährst du mehr darüber, wie Münzen in Sui funktionieren und wie du mit ihnen richtig umgehst: https://docs.sui.io/build/coin
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 reserviert25
- Wie interagieren Fähigkeitsbeschränkungen mit dynamischen Feldern in heterogenen Sammlungen?05