使用 32 (DESTROY_ACCOUNT_IF_ZERO) 标志时出现 TON 传输错误?

问题描述 投票:0回答:1

我一直在尝试重新使用被

DESTROY_ACCOUNT_IF_ZERO
(32) 标志删除的钱包。我的转账方式:

假设我们有 2 个钱包:A 和 B。

  1. 我们将
    N1
    TON 从
    A
    转移到
    B
    。例如。通过使用基于网络的钱包、脚本,并不重要。
  2. B
    未初始化 - 它尚未在区块链上。考虑到这一点,我们希望将所有来自
    B
    的钱汇回
    A
    。为此,我们将使用随附的脚本。
  3. 现在我们继续将
    N2
    TON 从
    A
    转移到
    B
    。多少都没关系。

预期行为:我们得到交易:

A->B (N1)
B->A (all)
A->B (N2)
;钱包
B
最终有
N2
吨。

实际行为:我们得到交易

A->B (N1)
B->A (all)
A->B (N2)
B->A (all)
;钱包
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

我还尝试从钱包

C
C->B
)发送TON。而且钱确实留在了
B
。但是当我再次转账
A->B
时,所有的钱,包括从
C
发送的TON,都会自动转到
A

此错误表现的示例(这是错误吗??)在这里:

https://tonviewer.com/EQAySjlsHUY2EEedO5GTenzFvAnR5E-4ptwfeox6OZYnNvGF

这是

B
钱包。脚本仅发送第一条带有“测试错误”文本的消息。其余的内容会在来自
A
的任何传入传输中自动发送。

在此互动中:

  • A
    UQAPqRlewultl8xHCKGsrenb4PZaQ0QDfPYoK1fwVUODdZRd
  • B
    EQAySjlsHUY2EEedO5GTenzFvAnR5E-4ptwfeox6OZYnNvGF
  • C
    UQBwpXsIVrij8UQ2OpPK2EyeVBrlN6mnOkmThb3k6K-UHZyL

我想了解为什么会发生这种情况。这是 TON 区块链开发者有意为之吗?这不是一个错误吗?如何解决这个问题并重新使用已删除的钱包?

javascript blockchain cryptocurrency ton
1个回答
0
投票

这不是一个错误。

传入区块链的消息会在节点的内存池中保留一段时间,直到它们的 TTL 用完。

我们钱包智能合约的初始状态是

seqno=0

Flag

DESTROY_ACCOUNT_IF_ZERO
(32) 销毁账户,因此钱包的智能合约在区块链中不再存在。我们通过
seqno=0
进行转账。

从钱包发送出转账后,钱包的智能合约会再次发布到区块链。这反过来意味着它的 seqno 又变成了

0
。因此,之前的消息仍然在内存池中,再次被执行。
所以,这实际上是 TON 区块链的一个非常奇特的行为。确实,它非常不规则,但绝不是一个错误。
    

© www.soinside.com 2019 - 2024. All rights reserved.