Пост
Поделитесь своими знаниями.
Чеканите монету 2 раза на один и тот же адрес
Если я чеканю монету 2 раза по одному и тому же адресу, суммы не суммируются. В тесте отображается только последняя монетная сумма?
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
Ответы
2проблема в том, что это разные Coin
объекты. В игре Sui Move каждая операция монетного двора создает новый <T>
объект Coin, а не автоматически комбинирует его с существующими монетами того же типа.
Поэтому вам нужно будет создать еще одну пробную транзакцию, чтобы получить оба монетных объекта и объединить их... как показано ниже
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();
}
Ключевые моменты:
При первой транзакции мы переводим исходную монету обратно отправителю, а не возвращаем ее
Во второй транзакции мы чеканяем новые монеты, в результате чего создается отдельный объект Coin
В третьей транзакции мы забираем обе монеты у отправителя
Используйте coin: :join, чтобы объединить их
Проверьте общую стоимость
Это соответствует реальному поведению Суя, когда каждый монетный двор создает новый предмет Coin
Кошельки обычно автоматически объединяют монеты
Вам необходимо явно объединять монеты в тестах, поскольку в тестовом сценарии они не объединяются автоматически.
Когда вы чеканите собственную монету несколько раз по одному и тому же адресу в Суе, каждый монетный двор создает отдельный Coin<T>
предмет, а не дополняет существующий. Поэтому, если вы проверите баланс, используя только одну монету, вы увидите стоимость одной монеты, обычно последней выпущенной монеты. Чтобы получить полный баланс, вам необходимо объединить все монетные объекты, принадлежащие вашему адресу. Coin<MY_COIN>
В тестах это означает, что нужно собрать все данныеcoin::merge
, принадлежащие отправителю, и объединить их. В противном случае тест покажет сумму только одной монеты, а не сумму всех выпущенных монет. Вот простой пример объединения двух монет после нескольких монет в блоке транзакций:
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));
Если вы чеканили несколько монет на один и тот же адрес, обязательно объединяйте их, прежде чем считывать баланс или использовать монеты в других операциях. Подробнее о том, как работают монеты в Sui и как правильно обращаться с ними, можно здесь: https://docs.sui.io/build/coin
Знаете ответ?
Пожалуйста, войдите в систему и поделитесь им.
Sui is a Layer 1 protocol blockchain designed as the first internet-scale programmable blockchain platform.
Заработай свою долю из 1000 Sui
Зарабатывай очки репутации и получай награды за помощь в развитии сообщества Sui.

- ... SUIMeaning.Sui+22
- ... SUI0xduckmove+17
- ... SUIMoonBags+11
- ... SUIHaGiang+10
- ... SUI
- ... SUIAliabee+5
- ... SUIBekky+5
- Почему BCS требует точного порядка полей для десериализации, когда структуры Move содержат именованные поля?53
- «Ошибки проверки нескольких источников» в публикациях модуля Sui Move — автоматическое устранение ошибок43
- Сбой транзакции Sui: объекты, зарезервированные для другой транзакции25
- Как ограничения возможностей взаимодействуют с динамическими полями в гетерогенных коллекциях?05