+
Skip to content

Sandbox error when testing DeDust example with USDT jetton-wallet (exit code 9: failed to load library cell) #128

@mysteryon88

Description

@mysteryon88

Description

While testing the DeDust example from the Tact cookbook, I encountered a VM crash when the vault tried to interact with the USDT jetton-wallet.

handling exception code 9: failed to load library cell
default exception handler, terminating vm with exit code 9
"@ton/blueprint": ">=0.40.0",
"@ton/sandbox": ">=0.37.0",

Steps to Reproduce

  1. npm create ton@latest
  2. Then a contract was written
//
// Helper structs described earlier on this page
//

struct SwapStep {
    poolAddress: Address;
    kind: Int as uint1 = 0;
    limit: Int as coins = 0;
    nextStep: Cell?;
}
struct SwapParams {
    deadline: Int as uint32 = 0;
    recipientAddress: Address? = null;
    referralAddress: Address? = null;
    fulfillPayload: Cell? = null;
    rejectPayload: Cell? = null;
}
/// https://docs.dedust.io/reference/tlb-schemes#message-swap
message(0xea06185d) NativeSwap {
    // Unique identifier used to trace transactions across multiple contracts
    // Defaults to 0, which means we don't mark messages to trace their chains
    queryId: Int as uint64 = 0;
    // Toncoin amount for the swap
    amount: Int as coins;
    // Inlined fields of SwapStep struct
    poolAddress: Address;
    kind: Int as uint1 = 0;
    limit: Int as coins = 0;
    nextStep: SwapStep? = null;
    // Set of parameters relevant for the whole swap
    swapParams: SwapParams;
}

/// https://docs.dedust.io/reference/tlb-schemes#message-swap-1
message(0xe3a0d482) JettonSwapPayload {
    // Inlined fields of SwapStep struct
    poolAddress: Address;
    kind: Int as uint1 = 0;
    limit: Int as coins = 0;
    nextStep: SwapStep? = null;

    // Set of parameters relevant for the entire swap
    swapParams: SwapParams;
}

message(0xf8a7ea5) JettonTransfer {
    queryId: Int as uint64;
    amount: Int as coins;
    destination: Address;
    responseDestination: Address;
    customPayload: Cell? = null;
    forwardTonAmount: Int as coins;
    forwardPayload: Cell?; // slightly adjusted
}

message SwapTon {
    swapAmount: Int;
}

message SwapJetton {
    swapAmount: Int;
    targetJettonWalletAddress: Address;
}

contract DeDust {
    receive(swap: SwapTon) {
        // Let's say `swapAmount` is `ton("0.1")`, which is 10000000 nanoToncoins
        send(SendParameters {
            // Address of the TON vault to send the message to
            to: address("EQDa4VOnTYlLvDJ0gZjNYm5PXfSmmtL6Vs6A_CZEtXCNICq_"),
            // Amount to swap plus a trade fee
            value: swap.swapAmount + ton("0.2"),
            body: NativeSwap {
                amount: swap.swapAmount,
                // Address of the swap pool, which is the TON/USDT pair in this case
                // poolAddress: address("EQAvtGe8Nep_XncmQYJrqzWjjdsTaygzL17bvH_8Rjryz1xu"), // DeDust Pool: TONNEL/TON
                poolAddress: address("EQA-X_yo3fzzbDbJ_0bzFWKqtRuZFIRa1sJsveZJ1YpViO3r"), // DeDust Pool: TON/USDT
                // Set of parameters relevant for the whole swap
                swapParams: SwapParams {}, // use defaults
            }.toCell(),
        });
    }

    receive(swap: SwapJetton) {
        send(SendParameters {
            to: swap.targetJettonWalletAddress,
            value: ton("0.3"),
            body: JettonTransfer {
                // Unique identifier used to trace transactions across multiple contracts.
                // Set to 0, which means we don't mark messages to trace their chains.
                queryId: 0,
                // Jetton amount for the swap.
                amount: swap.swapAmount, // NOTE: change to your amount
                // Address of the Jetton vault to send the message to.
                destination: address("EQC8jbJfR7Mu7K5oeyiIoHC3gWLmdCju2pUBucXqmQClB__N"), // DeDust Vault
                // Address to return any exceeding funds.
                responseDestination: myAddress(),
                forwardTonAmount: ton("0.25"),
                forwardPayload: JettonSwapPayload {
                    // Address of the swap pool, which is the TON/USDT pair in this case.
                    poolAddress: address("EQAvtGe8Nep_XncmQYJrqzWjjdsTaygzL17bvH_8Rjryz1xu"), // DeDust Pool: TONNEL/TON
                    // Set of parameters relevant for the entire swap.
                    swapParams: SwapParams {}, // use defaults
                }.toCell(),
            }.toCell(),
        });
    }

    receive() {
        cashback(sender());
    }
}
  1. Tests were implemented
import {
    Blockchain,
    SandboxContract,
    TreasuryContract,
    RemoteBlockchainStorage,
    wrapTonClient4ForRemote,
} from '@ton/sandbox';
import { TonClient4 } from '@ton/ton';
import { Address, fromNano, Sender, toNano } from '@ton/core';
import { DeDust } from '../build/DeDust/DeDust_DeDust';
import '@ton/test-utils';

describe('DeDust', () => {
    let blockchain: Blockchain;
    let deployer: SandboxContract<TreasuryContract>;
    let deDust: SandboxContract<DeDust>;

    beforeEach(async () => {
        blockchain = await Blockchain.create({
            storage: new RemoteBlockchainStorage(
                wrapTonClient4ForRemote(
                    new TonClient4({
                        endpoint: 'https://mainnet-v4.tonhubapi.com',
                    }),
                ),
            ),
        });

        deDust = blockchain.openContract(await DeDust.fromInit());

        deployer = await blockchain.treasury('deployer', {});

        const deployResult = await deDust.send(
            deployer.getSender(),
            {
                value: toNano('0.05'),
            },
            null,
        );

        expect(deployResult.transactions).toHaveTransaction({
            from: deployer.address,
            to: deDust.address,
            deploy: true,
            success: true,
        });
    });

    it('should deploy', async () => {
        console.log('My Balance', fromNano(await deployer.getBalance()));
        console.log('DeDustSwapper', fromNano((await blockchain.getContract(deDust.address)).balance));

        const TxResult = await deDust.send(
            deployer.getSender(),
            {
                value: toNano('1.3'),
            },
            { $$type: 'SwapTon', swapAmount: toNano(1) },
        );

        console.log(TxResult);

        console.log('My Balance', fromNano(await deployer.getBalance()));
        console.log('DeDustSwapper', fromNano((await blockchain.getContract(deDust.address)).balance));
    });
});
  1. Runnpx blueprint test

  2. You can find the error here

console.log(TxResult);

Environment

Windows 10

Logs or Screenshots

   {
          address: 61901089978021766573933745695147471064659099173648288175756929695054453318535n,
          lt: 61872258000011n,
          prevTransactionHash: 8089611070652109801654583336794466648641561177747294017534910868700693763909n,
          prevTransactionLt: 61872258000010n,
          now: 1758716651,
          outMessagesCount: 1,
          oldStatus: 'active',
          endStatus: 'active',
          inMessage: [Object],
          outMessages: [Dictionary],
          totalFees: [Object],
          stateUpdate: [Object],
          description: [Object],
          raw: x{788DAC67CCEADB9CAE6FAAC7118F05C0FA95DF36C2A92E686AC39D96310D0A38700003845C1F5A48B11E28EBF6639BEB6AB2706379E989EC368674F23F1A701B50445C0B4EF17974500003845C1F5A48A68D3E2EB0003461046A6}
           x{E_}
            x{680031551C5DDAA2E8FB5C06780F3727107B28395B1ECA8B3E5DD39AE8E96D71DABB002236B19F33AB6E72B9BEAB1C463C1703EA577CDB0AA4B9A1AB0E7658C43428E1D02BCE9340060E9DB20000708B83EB4914D1A7C5D6C_}
             x{0F8A7EA5000000000000000032B2436800355B48BEA2B7CC3AC4182DF9751CDE2C40E37A03F9AEE3EE8CA115DCBD0E29850006AB6917D456F987588305BF2EA39BC5881C6F407F35DC7DD19422BB97A1C5308810075520}
            x{DF_}
             x{580111B58CF99D5B7395CDF558E231E0B81F52BBE6D85525CD0D5873B2C621A1470F00062AA38BBB545D1F6B80CF01E6E4E20F65072B63D95167CBBA735D1D2DAE3B57502B9DBF400608235A0000708B83EB4918D1A7C5D67FFFFFFF87C53F528000000000000000195921B4001AADA45F515BE61D620C16FCBA8E6F4_}
           x{72AB820549B33D13008C60E8EA86C81686AE2E03D191DB0A37A814EEA86A32393BF8B9C591177C3C6CEE96F7BCD53B92EDCAF33BA63DFF6B3067939A63739A9205}
           x{040902BCE9341060C3500E0181046998208D6A_}
            x{407D0C1C095400000000120000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000},
          hash: [Function: hash],
          blockchainLogs: '[ 4][t 0][2025-09-24 12:24:11.633000][transaction.cpp:445]\tunpacking account 88DAC67CCEADB9CAE6FAAC7118F05C0FA95DF36C2A92E686AC39D96310D0A387\n' +
            '[ 4][t 0][2025-09-24 12:24:11.633000][transaction.cpp:278]\tlast_paid=0; cells=0 bits=0\n' +
            '[ 4][t 0][2025-09-24 12:24:11.633000][transaction.cpp:508]\tend of Account.unpack() for 0:88DAC67CCEADB9CAE6FAAC7118F05C0FA95DF36C2A92E686AC39D96310D0A387 (balance = 1799935430627ng ; last_trans_lt = 61872258000010..61872258000011)\n' +
            '[ 4][t 0][2025-09-24 12:24:11.633000][transaction.cpp:4006]\tblock random seed set to 0000000000000000000000000000000000000000000000000000000000000000\n' +
            '[ 4][t 0][2025-09-24 12:24:11.633000][transaction.cpp:1292]\tgas limits: max=1000000, limit=459349, credit=0\n' +
            '[ 4][t 0][2025-09-24 12:24:11.633000][transaction.cpp:1706]\tin_msg_state is null\n' +
            '[ 3][t 0][2025-09-24 12:24:11.633000][transaction.cpp:1785]\tUnknown precompiled contract (code_hash=89468F02C78E570802E39979C8516FC38DF07EA76A48357E0536F2BA7B3EE37B, gas_usage=1000), running VM\n' +
            '[ 4][t 0][2025-09-24 12:24:11.633000][transaction.cpp:1799]\tcreating VM\n' +
            '[ 4][t 0][2025-09-24 12:24:11.633000][transaction.cpp:1417]\tSmartContractInfo initialized with [ 124711402 0 0 1758716651 10000000 61872258000011 31001199375342540328671374741713225991918088502499606102394480502517547827387 [ 1800119170227 (null) ] CS{Cell{026dc0088dac67cceadb9cae6faac7118f05c0fa95df36c2a92e686ac39d96310d0a387000000000000000e11707d6922d8068c520c3f8d340} bits: 1..268; refs: 0..0} C{0BC9F6FFD54A6C031C516C4AD2CD9257D49DA3458F89C12B53F90A548D3BD668} C{89468F02C78E570802E39979C8516FC38DF07EA76A48357E0536F2BA7B3EE37B} [ 183739600 (null) ] 0 (null) [ CS{Cell{004dd06600000000000000000000000080000000000000fa00000000000001f4000000000003d09040} bits: 9..305; refs: 0..0} CS{Cell{0008ffffff11} bits: 0..32; refs: 0..0} CS{Cell{0094d1000000000000006400000000000f4240de000000002710000000000000000f424000000000042c1d80000000000000271000000000002625a00000000005f5e100000000003b9aca00} bits: 0..592; refs: 0..0} CS{Cell{0094d100000000000000640000000000009c40de000000000190000000000000000f424000000000000f4240000000000000271000000000009896800000000005f5e100000000003b9aca00} bits: 0..592; refs: 
0..0} CS{Cell{0042ea000000000098968000000000271000000000000f424000000001800055555555} bits: 0..264; refs: 0..0} CS{Cell{0042ea0000000000061a800000000001900000000000009c4000000001800055555555} bits: 0..264; refs: 0..0} (null) ] 0 1000 [ -1 0 CS{Cell{01b1680031551c5ddaa2e8fb5c06780f3727107b28395b1eca8b3e5dd39ae8e96d71dabb002236b19f33ab6e72b9beab1c463c1703ea577cdb0aa4b9a1ab0e7658c43428e1d02bce9340060e9db20000708b83eb4914d1a7c5d6c0} bits: 4..271; refs: 0..0} 478937 61872258000010 1758716651 183739600 183739600 (null) (null) ] ]\n' +
            '[ 4][t 0][2025-09-24 12:24:11.634000][transaction.cpp:1834]\tstarting VM\n' +
            '[ 4][t 0][2025-09-24 12:24:11.634000][transaction.cpp:1839]\tVM terminated with exit code 9\n' +
            '[ 3][t 0][2025-09-24 12:24:11.634000][transaction.cpp:1861]\tsteps: 2 gas: used=160, max=1000000, limit=1000000, credit=0\n' +
            '[ 3][t 0][2025-09-24 12:24:11.634000][transaction.cpp:1863]\tout_of_gas=false, accepted=true, success=false, time=0.000267s\n' +
            '[ 4][t 0][2025-09-24 12:24:11.634000][transaction.cpp:1898]\tgas fees: 400000 = 26214400 * 1000 /2^16 ; price=26214400; flat rate=[40000 for 100]; remaining balance=1800118770227ng\n',
          vmLogs: 'execute implicit JMPREF\n' +
            'handling exception code 9: failed to load library cell\n' +
            'default exception handler, terminating vm with exit code 9\n',
          debugLogs: '',
          oldStorage: undefined,
          newStorage: undefined,
          outActions: undefined,
          events: [Array],
          parent: [Object],
          children: [Array],
          externals: [],
          mode: 0
        },

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      点击 这是indexloc提供的php浏览器服务,不要输入任何密码和下载