-2

I'm developing a smart contract for TON blockchain in FunC and I'm trying to find a bug in my code. I'm trying to debug the issue and will appreciate something like console.log() from JavaScript so I can add prints / logs in strategic places and understand what's going on. Can this be done?

talkol
  • 12,564
  • 11
  • 54
  • 64

2 Answers2

1

The TVM has a special function for dumping variables in debug - ~dump

Run ~dump(variable_name); to print a variable's contents.

Run ~dump(12345); to print the number 12345.

Example:

() recv_internal(int msg_value, cell in_msg, slice in_msg_body) impure {

  ;; let's say I want to print the value of the variable msg_value
  
  ~dump(msg_value);
}

Please note that this command will not run on mainnet, so do not deploy production contracts with it. My favorite way to test smart contracts locally is using ton-contract-executor - this awesome library run a local version of the TVM in web-assembly right inside Node.js, which is very convenient for writing JavaScript/TypeScript tests.

To enable debug prints in ton-contract-executor, when you create your contract instance pass debug: true in SmartContractConfig and print the logs after interacting with the contract:

import { SmartContract } from "ton-contract-executor";

const contract = await SmartContract.fromCell(codeCell, dataCell, {
  debug: true // enable debug
});

const send = await contract.sendInternalMessage(...);

console.log(send.logs); // print the logs
talkol
  • 12,564
  • 11
  • 54
  • 64
0

For debugging real transaction in network, you can use this guide. It's pretty simple to see where something goes wrong.

Long story short:

  1. Install TON binaries (soon it'll be integrated into toncli) You can compile it manually or donwload prebuild from GH actions (you need to be authorized) GH actions
  2. Install toncli via pip install toncli
  3. Find your transaction in toncx -> example
  4. Copy logical time, transaction hash, account address (they are divided by :, just replace it with )
  5. Run toncli run_transaction [-h] [--net {testnet,mainnet}] [--function FUNCTION] [--save SAVE] logical_time transaction_hash smc_address

Working Example: toncli run_transaction -f 0 -n testnet 3473136000005 yPJU0r+TS1X5jL6lcXEI2s0jaGHtlLw9jTlasY2QnIw= EQAox8P13VjB0hNwZmHx3fxNc82xzjtZK5G5RR9gWc6zrxfI

Keep in mind that function selector is 0 for external messages and -1 is for internal messages.

You will see TVM OPs (with stack dump) and exit code, gas usage. This will really help you when you'll debug transactions.

 execute SDEQ
 [ CS{Cell{005300000000000000008005eca15cad9dab7f1677db60c75f9ecacd1e5c5eb2990df5a6bd03d89bfca208f0} bits: 64..331; refs: 0..0} CS{Cell{00166d795f6e66742e6a736f6e} bits: 0..88; refs: 0..0} 0 -1 ] 
execute THROWIFNOT 405
 [ CS{Cell{005300000000000000008005eca15cad9dab7f1677db60c75f9ecacd1e5c5eb2990df5a6bd03d89bfca208f0} bits: 64..331; refs: 0..0} CS{Cell{00166d795f6e66742e6a736f6e} bits: 0..88; refs: 0..0} 0 ] 
execute SWAP
 [ CS{Cell{005300000000000000008005eca15cad9dab7f1677db60c75f9ecacd1e5c5eb2990df5a6bd03d89bfca208f0} bits: 64..331; refs: 0..0} 0 CS{Cell{00166d795f6e66742e6a736f6e} bits: 0..88; refs: 0..0} ] 
execute LDMSGADDR
handling exception code 9: cannot load a MsgAddress
default exception handler, terminating vm with exit code 9
[ 3][t 0][2022-09-01 13:52:06.274723355][vm.cpp:558]    steps: 58 gas: used=2170, max=9223372036854775807, limit=9223372036854775807, credit=0