Publication
Partagez vos connaissances.
Monnaie frappée 2 fois à la même adresse
Si je frappe ma pièce deux fois à la même adresse, les montants ne s'additionnent pas. Seul le montant de la dernière monnaie apparaît lors du test ?
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
Réponses
2le problème, c'est qu'il s'agit Coin
d'objets différents. Dans Sui Move, chaque opération de frappe crée un nouvel <T>
objet Coin au lieu de le combiner automatiquement avec des pièces existantes du même type.
Vous devrez donc créer une autre transaction fictive pour obtenir les deux pièces et les rejoindre... comme indiqué ci-dessous
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();
}
Points clés :
Lors de la première transaction, nous renvoyons la pièce initiale à l'expéditeur au lieu de la renvoyer
Lors de la deuxième transaction, nous frappons de nouvelles pièces, ce qui crée un objet Coin distinct
Lors de la troisième transaction, nous prenons les deux pièces de l'expéditeur
Utilisez coin : :join pour les combiner
Vérifiez la valeur totale
Cela correspond au comportement réel de Sui, où chaque monnaie crée un nouvel objet Coin
Les portefeuilles combinent généralement les pièces automatiquement
Vous devez joindre explicitement des pièces dans les tests car le scénario de test ne les combine pas automatiquement.
Lorsque vous frappez votre pièce personnalisée plusieurs fois à la même adresse sur Sui, chaque monnaie crée un Coin<T>
objet distinct au lieu d'en ajouter à un objet existant. Ainsi, lorsque vous vérifiez le solde à l'aide d'une seule pièce, vous ne verrez que la valeur de cette pièce, généralement la dernière frappée. Pour obtenir le solde complet, vous devez fusionner toutes les pièces appartenant à votre adresse. Coin<MY_COIN>
Dans les tests, cela signifie qu'il faut saisir chacune des propriétés coin::merge
de l'expéditeur et les combiner à l'aide de celles-ci. Sans cela, le test n'indiquera que le montant d'une pièce, et non le total de toutes les pièces frappées. Voici un exemple simple de fusion de deux pièces après plusieurs opérations dans un bloc de transaction :
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 vous avez frappé plusieurs pièces à la même adresse, assurez-vous toujours de les fusionner avant de lire le solde ou d'utiliser les pièces pour d'autres opérations. Pour en savoir plus sur le fonctionnement des pièces en Sui et sur la manière de les gérer correctement, cliquez ici : https://docs.sui.io/build/coin
Connaissez-vous la réponse ?
Veuillez vous connecter et la partager.
Sui is a Layer 1 protocol blockchain designed as the first internet-scale programmable blockchain platform.
Gagne ta part de 1000 Sui
Gagne des points de réputation et obtiens des récompenses pour avoir aidé la communauté Sui à se développer.

- ... SUIMeaning.Sui+22
- ... SUI0xduckmove+17
- ... SUIMoonBags+11
- ... SUIHaGiang+10
- ... SUI
- ... SUIAliabee+5
- ... SUIBekky+5
- Pourquoi BCS exige-t-il un ordre de champs exact pour la désérialisation alors que les structures Move ont des champs nommés ?53
- « Erreurs de vérification de sources multiples » dans les publications du module Sui Move - Résolution automatique des erreurs43
- Échec de la transaction Sui : objets réservés pour une autre transaction25
- Comment les contraintes de capacité interagissent-elles avec les champs dynamiques dans des collections hétérogènes ?05