Skip to content

Commit

Permalink
add descriptions for edge cases in fireworks-func
Browse files Browse the repository at this point in the history
  • Loading branch information
aSpite committed Jan 24, 2024
1 parent 89338e0 commit d64662a
Showing 1 changed file with 147 additions and 0 deletions.
147 changes: 147 additions & 0 deletions docs/develop/smart-contracts/testing/writing-test-examples.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -434,5 +434,152 @@ This test verifies whether the transaction fees for launching the fireworks are

```

## Edge Cases Tests

In this section will be provided the test cases for TVM exit [codes](/learn/tvm-instructions/tvm-exit-codes) that can occur during transaction processing. These exit codes are in the blockchain code itself. At the same time, it is necessary to distinguish the exit code during the [Compute Phase](/learn/tvm-instructions/tvm-overview#compute-phase) and the exit code during the Action Phase.

During the Compute Phase, the contract logic (its code) is executed. While processing, various actions can be created. These actions will be processed in the next phase - Action Phase. If the Compute Phase is unsuccessful, then the Action Phase does not start. However, if the Compute Phase was successful, this does not guarantee that the Action Phase will also end successfully.

### Compute Phase | exit code = 0

This exit code means that the Compute Phase of the transaction was completed successfully.

### Compute Phase | exit code = 1

A alternative exit code for denoting the success of the Compute Phase is `1`. To get this exit code, you need to use the [RETALT](https://github.com/ton-community/fireworks-func/blob/ef49b4da12d287a8f6c2b6f0c19d65814c1578fc/contracts/fireworks.fc#L20).

It should be noted that this opcode should be called in the main function (for example, recv_internal). If you call in another function, then the exit from that function will be `1`, but the total exit code will be `0`.

### Compute Phase | exit code = 2

TVM is a [stack machine](/learn/tvm-instructions/tvm-overview#tvm-is-a-stack-machine). When interacting with different values, they appear on the stack. If suddenly there are no elements on the stack, but some opcode requires them, then this error is thrown.

This can happen when working with opcodes directly, since [stdlib.fc](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/stdlib.fc) (a library for FunC) assumes that there will be no such problem.

### Compute Phase | exit code = 3

Any code before execution becomes a `continuation`. This is a special data type that contains a slice with code, a stack, registers, and other data necessary for the execution of the code. Such a continuation can be run later if necessary, passing the necessary parameters for the initial state of the stack.

First, we [build](https://github.com/ton-community/fireworks-func/blob/ef49b4da12d287a8f6c2b6f0c19d65814c1578fc/contracts/fireworks.fc#L31-L32) such a continuation. In this case, this is just an empty continuation that does nothing. Next, using the opcode `0 SETNUMARGS`, we indicate that there should be no values ​​in the stack at the beginning of execution. Then, using the opcode `1 -1 SETCONTARGS`, we call the continuation, passing 1 value. Since there should have been no values, we get a StackOverflow error.

### Compute Phase | exit code = 4

In TVM, `integer` can be in the range -2<sup>256</sup> < x < 2<sup>256</sup>. If the value during the calculation went beyond this range, then 4 exit code is thrown.

### Compute Phase | exit code = 5

If the `integer` value went beyond the expected range, then 5 exit code is thrown. For example, if a negative value was used in the `.store_uint()` function.

### Compute Phase | exit code = 6

On a lower level, instead of the familiar functions names, opcodes are used, which can be seen in [this table](/learn/archive/tvm-instructions) in HEX form. In this example, we [use](https://github.com/ton-community/fireworks-func/blob/ef49b4da12d287a8f6c2b6f0c19d65814c1578fc/contracts/fireworks.fc#L25) `@addop`, which adds a non-existent opcode.

The emulator, when trying to process this opcode, does not recognize it and throws 6.

### Compute Phase | exit code = 7

It is a quite common error that occurs when receiving the wrong data type. In [example](https://github.com/ton-community/fireworks-func/blob/ef49b4da12d287a8f6c2b6f0c19d65814c1578fc/contracts/fireworks.fc#L79-L80) is the case when the `tuple` contained 3 elements, but when unpacking there was an attempt to get 4.

There are many other cases when this error is thrown. Some of them:

- [not a null](https://github.com/ton-blockchain/ton/blob/9728bc65b75defe4f9dcaaea0f62a22f198abe96/crypto/vm/stack.cpp#L433)
- [not an integer](https://github.com/ton-blockchain/ton/blob/9728bc65b75defe4f9dcaaea0f62a22f198abe96/crypto/vm/stack.cpp#L441)
- [not a cell](https://github.com/ton-blockchain/ton/blob/9728bc65b75defe4f9dcaaea0f62a22f198abe96/crypto/vm/stack.cpp#L478)
- [not a cell builder](https://github.com/ton-blockchain/ton/blob/9728bc65b75defe4f9dcaaea0f62a22f198abe96/crypto/vm/stack.cpp#L500)
- [not a cell slice](https://github.com/ton-blockchain/ton/blob/9728bc65b75defe4f9dcaaea0f62a22f198abe96/crypto/vm/stack.cpp#L509)
- [not a string](https://github.com/ton-blockchain/ton/blob/9728bc65b75defe4f9dcaaea0f62a22f198abe96/crypto/vm/stack.cpp#L518)
- [not a bytes chunk](https://github.com/ton-blockchain/ton/blob/9728bc65b75defe4f9dcaaea0f62a22f198abe96/crypto/vm/stack.cpp#L527)
- [not a continuation](https://github.com/ton-blockchain/ton/blob/9728bc65b75defe4f9dcaaea0f62a22f198abe96/crypto/vm/stack.cpp#L536)
- [not a box](https://github.com/ton-blockchain/ton/blob/9728bc65b75defe4f9dcaaea0f62a22f198abe96/crypto/vm/stack.cpp#L545)
- [not a tuple](https://github.com/ton-blockchain/ton/blob/9728bc65b75defe4f9dcaaea0f62a22f198abe96/crypto/vm/stack.cpp#L554)
- [not an atom](https://github.com/ton-blockchain/ton/blob/9728bc65b75defe4f9dcaaea0f62a22f198abe96/crypto/vm/stack.cpp#L598)

### Compute Phase | exit code = 8

All data in TON is stored in [cells](/develop/data-formats/cell-boc#cell). A cell has the capacity to store 1023 bits of data and 4 references to other cells. If you try to write more than 1023 bits or more than 4 references, 8 exit code is thrown.

### Compute Phase | exit code = 9

If you try to read more data from a slice (when reading data from a cell, it must be converted to a slice data type) than it contains, then 9 exit code is thrown. For example, if there were 10 bits in the slice, and 11 were read, or if there were no links to other references, but there was an attempt to load a reference.

### Compute Phase | exit code = 10

This error is thrown when working with [dictionaries](/develop/func/stdlib/#dictionaries-primitives). As an example, the case when the value that belongs to the key [is stored in another cell](https://github.com/ton-community/fireworks-func/blob/ef49b4da12d287a8f6c2b6f0c19d65814c1578fc/contracts/fireworks.fc#L100-L110) as a reference. In this case, you need to use the `.udict_get_ref()` function to get such a value.

However, the link to another cell [should be only 1](https://github.com/ton-blockchain/ton/blob/9728bc65b75defe4f9dcaaea0f62a22f198abe96/crypto/vm/dict.cpp#L454) and not 2, as in our example:

```
root_cell
├── key
│ ├── value
│ └── value - second reference for one key
└── key
└── value
```
That is why when trying to read the value, we get 10 exit code.

**Additional:** You can also store the value next to the key in the dictionary:

```
root_cell
├── key-value
└── key-value
```

**Note:** In fact, the structure of the dictionary (how the data is located in the cells) is more complicated than indicated in the examples above. Therefore, they are simplified for understanding the example.

### Compute Phase | exit code = 11

This error occurs when something unknown happens. For example, when using the [SENDMSG](/learn/tvm-instructions/tvm-upgrade-2023-07#sending-messages) opcode, if you pass the [wrong](https://github.com/ton-community/fireworks-func/blob/ef49b4da12d287a8f6c2b6f0c19d65814c1578fc/contracts/fireworks.fc#L116) (for example, empty) cell with a message, then such an error will occur.

Also, it occurs when trying to call a non-existent method. Often, developers face this when calling a non-existent GET method.

### Compute Phase | exit code = -14 (13)

If there is not enough TON to handle Compute Phase, then this error is thrown. In the enum class `Excno`, where the exit codes for various errors in Compute Phase are indicated, [the value 13 is indicated](https://github.com/ton-blockchain/ton/blob/9728bc65b75defe4f9dcaaea0f62a22f198abe96/crypto/vm/excno.hpp#L39).

However, during processing, the [NOT operation is applied](https://github.com/ton-blockchain/ton/blob/9728bc65b75defe4f9dcaaea0f62a22f198abe96/crypto/block/transaction.cpp#L1574) to this value, which changes this value to `-14`. This is done so that this exit code cannot be faked using, for example, the `throw` function, since all such functions accept only positive values for the exit code.

### Action Phase | exit code = 32

Action Phase begins after Compute Phase and it processes actions that were written to [register c5](/learn/tvm-instructions/tvm-initialization#control-register-c5) during Compute Phase. If the data in this register is incorrectly written, then 32 exit code will be thrown.

### Action Phase | exit code = 33

At the moment, a maximum of `255` actions can be in one transaction. If this value is exceeded, then the Action Phase will end with 33 exit code.

### Action Phase | exit code = 34

This exit code is responsible for most of the errors when working with actions: invalid message, incorrect action, and so on.

### Action Phase | exit code = 35

During the building of the [CommonMsgInfo](/develop/smart-contracts/tutorials/wallet#commonmsginfo) part of the message, you must specify the correct source address. It must be equal to either [addr_none](/develop/data-formats/msg-tlb#addr_none00) or the address of the account that sends the message.

In the blockchain code, this is handled by the [check_replace_src_addr](https://github.com/ton-blockchain/ton/blob/9728bc65b75defe4f9dcaaea0f62a22f198abe96/crypto/block/transaction.cpp#L1985).

### Action Phase | exit code = 36

If the destination address is invalid, then 36 exit code is thrown. Some possible reasons are a non-existent workchain or an incorrect address. All checks can be seen in the [check_rewrite_dest_addr](https://github.com/ton-blockchain/ton/blob/9728bc65b75defe4f9dcaaea0f62a22f198abe96/crypto/block/transaction.cpp#L2014-L2113).

### Action Phase | exit code = 37

This exit code is similar to `-14` in Compute Phase. Here it means that there is not enough balance to send the specified amount of TON.

### Action Phase | exit code = 38

The same as in `37` exit code, but refers to the lack of [ExtraCurrency](/develop/research-and-development/minter-flow#extracurrency) on the balance.

### Action Phase | exit code = 40

In case there is enough TON to process a certain part of the message (let's say 5 cells), and there are 10 cells in the message, 40 exit code is thrown.

### Action Phase | exit code = 43

May be occur, if the maximum number of cells in the library is exceeded or the maximum depth of the Merkle tree is exceeded.

Library is a cell that is stored in [Masterchain](/learn/overviews/ton-blockchain#masterchain-blockchain-of-blockchains) and can be used by all smart contracts if it is [public](https://github.com/ton-blockchain/ton/blob/9728bc65b75defe4f9dcaaea0f62a22f198abe96/crypto/block/transaction.cpp#L1844).

:::info
Since the order of lines may change when updating the code, some links become irrelevant. Therefore, all links will use the state of the code base at commit [9728bc65b75defe4f9dcaaea0f62a22f198abe96](https://github.com/ton-blockchain/ton/tree/9728bc65b75defe4f9dcaaea0f62a22f198abe96).
:::

0 comments on commit d64662a

Please sign in to comment.