blueprint icon indicating copy to clipboard operation
blueprint copied to clipboard

In cases of Cell underflow/overflow or other similar exit codes, contract's debug output doesn't show anything

Open novusnota opened this issue 1 year ago • 1 comments

See the following Tact snippet and comments in it:

import "@stdlib/deploy";

struct Coin {
    first: Int as coins;
    second: Int as uint32;
}

fun directParse(payload: Cell): Coin {
    return Coin.fromCell(payload);
}

contract Example with Deployable {
    receive("example") {
        let coin = directParse(
            beginCell()
            .storeCoins(42)
            .storeUint(35, 31) // here, I only specified 31 bit for storing the Uint, but could've specified 33 bits and get the same issue
            .endCell()
        );
        dump(coin.first); // would display nothing!
        dump(coin.second); // neither would this!
    }
}

And the Example.spec.ts file, which simply sends a message to the "example" receiver:

import { Blockchain, SandboxContract, TreasuryContract, printTransactionFees, prettyLogTransaction, prettyLogTransactions } from '@ton/sandbox';
import { Dictionary, Transaction, beginCell, toNano } from '@ton/core';
import { Example } from '../wrappers/Example';
import '@ton/test-utils';

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

  beforeEach(async () => {
    blockchain = await Blockchain.create();
    example = blockchain.openContract(await Example.fromInit());
    deployer = await blockchain.treasury('deployer');

    const deployResult = await example.send(
      deployer.getSender(),
      { value: toNano('0.05') },
      { $$type: 'Deploy', queryId: 0n },
    );

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

    blockchain.now = deployResult.transactions[2].now;
  });

  it('plays', async () => {
    await example.send(
      deployer.getSender(),
      { value: toNano('0.5') },
      'example',
    );
  });
});

Test suite of Jest just goes through and there's nothing in #DEBUG# output, as if those calls to dump() didn't happen. This may be a @ton/sandbox issue, but an expected outcome is to see error with an exit code 9, Cell underflow for the given example above.

novusnota avatar Jun 28 '24 12:06 novusnota

@novusnota Could you also add the .spec.ts file you used for testing here. It will be useful to come up fix a fix and a test for that fix

anton-trunov avatar Jun 28 '24 12:06 anton-trunov

Hey! I probably somehow misunderstood the issue. If we change the lines like this:

import "@stdlib/deploy";

struct Coin {
    first: Int as coins;
    second: Int as uint32;
}

fun directParse(payload: Cell): Coin {
    return Coin.fromCell(payload);
}

contract Example with Deployable {
    receive("example") {
        dump("hey!"); // displays
        let coin = directParse(
        beginCell()
        .storeCoins(42)
        .storeUint(35, 31) // here, I only specified 31 bit for storing the Uint, but could've specified 33 bits and get the same issue
        .endCell()
        );
        dump(coin.second); // neither would this!
    }
}

and check the exit code

it('plays', async () => {
        const res = await example.send(
            deployer.getSender(),
            { value: toNano('0.5') },
            'example',
        );

        expect(res.transactions).toHaveTransaction({
            success: false,
            exitCode: 9,
        })
    });

It would find transaction with exitCode 9 and display the output for the first debug statement like following:

    #DEBUG#: File contracts/test.tact:14:9:
    #DEBUG#: dump("hey!")
    #DEBUG#: hey!

@novusnota Could you please clarify, what is the desired outcome of the example below? Or maybe this issue is outdated?

Alejandbel avatar Apr 30 '25 13:04 Alejandbel

Could you please clarify, what is the desired outcome of the example below? Or maybe this issue is outdated?

My point was to notify when the debug output is truncated due to the errors in the transaction because that's not clear if there's no such success: false, exitCode: 9 check added explicitly.

That's a minor pain point when using Blueprint for printf debugging where you don't know which exit code happened and why (it was unexpected, so there were no expect() clauses).

That said, I don't know if this issue should be solved by extra messages in the console noticing about exit codes OR by introducing a special .send()-like function that, aside from sending a message, would attempt to trace unsuccessful transactions and print related info regardless of expect() clauses. Hence, I'll close this issue.

Feel free to re-open it if you have any suggestions though :)

novusnota avatar May 01 '25 14:05 novusnota