Я пытался повторно использовать кошелек, удаленный с помощью флага DESTROY_ACCOUNT_IF_ZERO (32). Способ, которым я осуществляю перевод:
Представьте, что у нас есть 2 кошелька: A и B.
Мы переводим N1 тонну из "A" в "B". Например, с помощью веб-кошелька, скрипта, не имеет значения. 2. B неинициализирован - его еще нет в блокчейне. Имея это в виду, мы хотели бы отправить все деньги из B обратно в A. Для этого мы собираемся использовать прилагаемый скрипт. 3. Теперь мы идем дальше и переносим N2 ТОННЫ из A в B ** снова **. Не имеет значения, сколько.
Ожидаемое поведение: мы получаем транзакции: A->B (N1), B->A (все), A->B (N2); в конечном итоге в кошельке B содержится N2 тонн.
Фактическое поведение: мы получаем транзакции A->B (N1), B->A (все), A->B (N2), B->A (все); в кошельке B в итоге 0 тонн.
Сценарий для передачи B->A (all), который вызывает такое поведение:
import TonWeb from 'tonweb';
import tonwebMnemonic from 'tonweb-mnemonic';
const apiKey = "" || undefined;
// WALLET B
const mnemonic = "...";
const walletVersion = "v4R2";
// WALLET A
const toAddress = "...";
const SendMode = {
CARRY_ALL_REMAINING_BALANCE: 128,
CARRY_ALL_REMAINING_INCOMING_VALUE: 64,
DESTROY_ACCOUNT_IF_ZERO: 32,
PAY_GAS_SEPARATELY: 1,
IGNORE_ERRORS: 2,
NONE: 0
}
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
(async () => {
const provider = new TonWeb.HttpProvider('https://toncenter.com/api/v2/jsonRPC', {apiKey});
const WalletClass = TonWeb.Wallets.all[walletVersion];
const mnemonicArray = mnemonic.split(" ");
let { publicKey, secretKey } = await tonwebMnemonic.mnemonicToKeyPair(mnemonicArray);
publicKey = Buffer.from(publicKey);
secretKey = Buffer.from(secretKey);
console.log(`PUBLIC KEY: ${publicKey.toString('hex')}`);
const wallet = new WalletClass(provider, { publicKey });
const seqno = await wallet.methods.seqno().call() || 0;
console.log(`SEQNO: ${seqno}`);
await sleep(2000);
const transferParams = {
secretKey,
toAddress,
amount: 0,
seqno,
sendMode: SendMode.CARRY_ALL_REMAINING_BALANCE | SendMode.IGNORE_ERRORS | SendMode.DESTROY_ACCOUNT_IF_ZERO,
payload: "test bug"
};
console.log(JSON.stringify({...transferParams, secretKey: transferParams.secretKey.toString('hex')}, null, 2));
const response = await wallet.methods.transfer(transferParams).send();
console.log(`transfer sent to blockchain: ${JSON.stringify(response, null, 2)}`);
})();
Странная вещь: если вы отправите A->B (N) снова, он автоматически создаст новую передачу B->A (all) снова и снова. Иногда она останавливается на 2 повторениях, иногда на 4.
Я использую недоступный адрес: UQAPqRlewultl8xHCKGsrenb4PZaQ0QDfPYoK1fwVUODdZRd.
Я также попробовал отправить TON с кошелька "C (C->B). И деньги ДЕЙСТВИТЕЛЬНО остались на B`. НО как только я снова сделал перевод "A->B", все деньги, включая тонны, отправленные с "C", автоматически перешли на "A"!
Пример проявления этой ошибки (это ошибка??) находится здесь:
https://tonviewer.com/EQAySjlsHUY2EEedO5GTenzFvAnR5E-4ptwfeox6OZYnNvGF
Это кошелек B. Скрипт отправил только первое сообщение с текстом "тестовая ошибка". Остальные сообщения отправлялись автоматически при любом входящем переводе с A.
В этом взаимодействии:
A is UQAPqRlewultl8xHCKGsrenb4PZaQ0QDfPYoK1fwVUODdZRd * B is EQAySjlsHUY2EEedO5GTenzFvAnR5E-4ptwfeox6OZYnNvGF * C is UQBwpXsIVrij8UQ2OpPK2EyeVBrlN6mnOkmThb3k6K-UHZyL
Я хочу понять, почему это происходит. Это задумано разработчиками блокчейна TON? Это не ошибка? Как обойти это и повторно использовать удаленные кошельки?
Оригинал вопроса