Sui.

Beitrag

Teile dein Wissen.

Meaning.Sui.
Jul 09, 2025
Experten Q&A

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
0
2
Teilen
Kommentare
.

Antworten

2
HaGiang.
Jul 9 2025, 07:51

Das Problem ist, dass es sich um unterschiedliche CoinObjekte 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.

0
Kommentare
.
24p30p.
Jul 9 2025, 21:07

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::mergedas 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

0
Kommentare
.

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.

386Beiträge541Antworten
Sui.X.Peera.

Verdiene deinen Anteil an 1000 Sui

Sammle Reputationspunkte und erhalte Belohnungen für deine Hilfe beim Wachstum der Sui-Community.

BelohnungskampagneJuli