Sui.

Publicación

Comparte tu conocimiento.

Meaning.Sui.
Jul 09, 2025
P&R expertos

Moneda acuñada 2 veces en la misma dirección

Si acuño mi moneda 2 veces en la misma dirección, las cantidades no cuadran. ¿Solo aparece la última cantidad acuñada en la prueba?

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
Cuota
Comentarios
.

Respuestas

2
HaGiang.
Jul 9 2025, 07:51

el problema es porque son Coinobjetos diferentes. En Sui Move, cada operación de acuñación crea un nuevo <T>objeto de moneda en lugar de combinarlo automáticamente con monedas existentes del mismo tipo.

Así que tendrás que crear otro simulacro de transacción para conseguir ambas monedas y unirlas... tal y como se muestra a continuación

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();
}

Puntos clave:

En la primera transacción, transferimos la moneda inicial al remitente en lugar de devolverla

En la segunda transacción, acuñamos monedas nuevas, lo que crea un objeto Coin independiente

En la tercera transacción, tomamos ambas monedas del remitente

Usa coin: :join para combinarlas

Verifica el valor total

Esto coincide con el comportamiento real de los Sui, donde cada ceca crea un nuevo objeto de moneda

Los monederos suelen combinar monedas automáticamente

Debes unir las monedas de forma explícita en las pruebas, ya que el escenario de prueba no las combina automáticamente.

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

Cuando acuñas tu moneda personalizada varias veces en la misma dirección en Sui, cada casa de moneda crea un Coin<T>objeto diferente en lugar de añadirlo al existente. Por lo tanto, cuando compruebes el saldo con una sola moneda, solo verás el valor de esa moneda, normalmente la última acuñada. Para obtener el saldo total, debes combinar todas las monedas que pertenezcan a tu dirección. Coin<MY_COIN>En las pruebas, esto significa coger cada una de las que coin::mergeposee el remitente y combinarlas con ellas. Sin hacer esto, la prueba solo mostrará la cantidad de una moneda, no el total de todas las monedas acuñadas. Este es un ejemplo básico de cómo fusionar dos monedas después de varias acuñaciones en un bloque de transacciones:

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));

Si acuñaste varias monedas en la misma dirección, asegúrate siempre de combinarlas antes de leer el saldo o usar las monedas en otras operaciones. Puedes obtener más información sobre cómo funcionan las monedas en Sui y cómo manejarlas correctamente aquí: https://docs.sui.io/build/coin

0
Comentarios
.

Sabes la respuesta?

Inicie sesión y compártalo.

Sui is a Layer 1 protocol blockchain designed as the first internet-scale programmable blockchain platform.

394Publicaciones554Respuestas
Sui.X.Peera.

Gana tu parte de 1000 Sui

Gana puntos de reputación y obtén recompensas por ayudar a crecer a la comunidad de Sui.

Campaña de RecompensasJulio