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 22, 2024
1 parent 019ba7d commit d004e9c
Showing 1 changed file with 124 additions and 0 deletions.
124 changes: 124 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,129 @@ This test verifies whether the transaction fees for launching the fireworks are

```

## Edge Cases Tests

Здесь будут примеры разных ошибок, которые могут быть во время обработки транзакции. Эти exit codes есть в самом коде блокчейна.

:::info
Так как при обновлениях кода порядок строк может меняться, некоторые ссылки становятся неактуальными. Поэтому во всех ссылках будет использоваться состояние кодовой базы на коммит `9728bc65b75defe4f9dcaaea0f62a22f198abe96`.
:::

### Compute Phase | exit code = 0

Этот exit code обозначает, что Compute Phase транзакции завершился успешно.

### Compute Phase | exit code = 1

Альтернативным exit code для обозначения успешности Compute Phase является `1`. Для того, чтобы получить этот exit code, необходимо использовать опкод [RETALT](https://github.com/ton-community/fireworks-func/blob/ef49b4da12d287a8f6c2b6f0c19d65814c1578fc/contracts/fireworks.fc#L20).

При этом стоит учесть, что вызывать этот опкод нужно в главной функции (например, recv_internal). Если вызывать в другой функции, то выход из той функции будет равен `1`, но общий код выхода - `0`.

### Compute Phase | exit code = 2

Как известно, TVM является [стековой машиной](/learn/tvm-instructions/tvm-overview#tvm-is-a-stack-machine). При взаимодействии с разными значениями они появляются на стеке. Если вдруг на стеке не осталось элементов, но какой-то опкод требует их, то выбрасывается эта ошибка.

Такое может произойти при работе с опкодами напрямую, так как [stdlib.fc](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/stdlib.fc) (библиотека для FunC) предусматривает, что такой проблемы не будет.

### Compute Phase | exit code = 3

Любой код перед исполнением становится `continuation`. Это такой специальный тип данных, который содержит slice с кодом, стек, регистры и другие данные, необходимые для исполнения кода. Такой continuation можно запускать позже при необходимости, передавая нужные параметры для начального состояния стека.

Для начала мы [собираем](https://github.com/ton-community/fireworks-func/blob/ef49b4da12d287a8f6c2b6f0c19d65814c1578fc/contracts/fireworks.fc#L31-L32) такой continuation. В данном случае это просто пустой continuation, который ничего не делает. Далее при помощи опкода `0 SETNUMARGS` указываем, что в стеке в начале исполнения не должно быть значений. Затем с помощью опкода `1 -1 SETCONTARGS` вызываем continuation, передавая 1 значение. Так как значений не должно было быть, получаем ошибку StackOverflow.

### Compute Phase | exit code = 4

В TVM `integer` может быть в диапазоне -2<sup>256</sup> < x < 2<sup>256</sup>. Если значение в ходе вычислений вышло за рамки этого диапазона, то выбрасывается 4 exit code.

### Compute Phase | exit code = 5

Если значение `integer` вышло за пределы ожидаемого диапазона, то получается 5 exit code. Например, если в функции `.store_uint()` было использовано отрицательное значение.

### Compute Phase | exit code = 6

На более низком уровне вместо привычных нам названий используются опкоды, которые можно увидеть в [этой таблице](/learn/archive/tvm-instructions) в HEX форме. В этом примере мы [используем](https://github.com/ton-community/fireworks-func/blob/ef49b4da12d287a8f6c2b6f0c19d65814c1578fc/contracts/fireworks.fc#L25) `@addop`, который добавляет несуществующий опкод.

Эмулятор при попытке обработать этот опкод не узнаёт его и выбрасывает 6.

### Compute Phase | exit code = 7

Это довольно общая ошибка, которая возникает при получении неправильного типа данных. В [примере](https://github.com/ton-community/fireworks-func/blob/ef49b4da12d287a8f6c2b6f0c19d65814c1578fc/contracts/fireworks.fc#L79-L80) указан случай, при котором `tuple` содержал 3 элемента, но при распаковке была попытка получить 4.

Есть много других случаев, когда выбрасывается эта ошибка. Некоторые из них:
- [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

В TON всё является [cell](/develop/data-formats/cell-boc#cell). Одна ячейка может вместить в себя 1023 бит данных и 4 ссылки на другие ячейки. При попытке записать более 1023 бит или более 4 ссылок выбрасывается 8 exit code.

### Compute Phase | exit code = 9

Если попытаться прочитать из ячейки больше данных, чем в ней хранится, то выбрасывается 9 exit code.

### Compute Phase | exit code = 10

Эта ошибка выбрасывается при ошибка во время работы со [словарями](/develop/func/stdlib/#dictionaries-primitives). В качестве примера взят случай, когда значение, которое относится к ключу [хранится в другой ячейке](https://github.com/ton-community/fireworks-func/blob/ef49b4da12d287a8f6c2b6f0c19d65814c1578fc/contracts/fireworks.fc#L100-L110) в качестве ссылки. В данном случае необходимо использовать функцию `.udict_get_ref()` для получения такого значения.

Однако ссылка на другую ячейку [должна быть всего 1](https://github.com/ton-blockchain/ton/blob/9728bc65b75defe4f9dcaaea0f62a22f198abe96/crypto/vm/dict.cpp#L454), а не 2, как в нашем примере. Поэтому при попытке прочитать значение мы получаем 10 exit code.

### Compute Phase | exit code = 11

Эта ошибка возникает, когда происходит что-то неизвестное. Например, если при использовании опкода [SENDMSG](/learn/tvm-instructions/tvm-upgrade-2023-07#sending-messages) передать [неправильную](https://github.com/ton-community/fireworks-func/blob/ef49b4da12d287a8f6c2b6f0c19d65814c1578fc/contracts/fireworks.fc#L116) (например, пустую) ячейку с сообщением, то возникнет такая ошибка.

Также эта ошибка возникает при попытке вызвать несуществующий метод. Зачастую разработчики сталкиваются с этим при вызове несуществующего GET метода.

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

Данная ошибка отвечает за случай, когда во время обработки Compute Phase закончились TON. В enum class `Excno`, где указаны коды выходов для различных ошибок на Compute Phase [указано значение 13](https://github.com/ton-blockchain/ton/blob/9728bc65b75defe4f9dcaaea0f62a22f198abe96/crypto/vm/excno.hpp#L39).

Однако во время обработки к этому коду [применяется операция NOT](https://github.com/ton-blockchain/ton/blob/9728bc65b75defe4f9dcaaea0f62a22f198abe96/crypto/block/transaction.cpp#L1574), что меняет это значение на `-14`. Это сделано для того, чтобы этот exit code нельзя было подделать при помощи, например, функции `throw`, так как все подобные функции принимают только положительные значения для exit code.

### Action Phase | exit code = 32

Action Phase начинается после Compute Phase и в нём обрабатываются actions, которые были записаны в [регистр c5](/learn/tvm-instructions/tvm-initialization#control-register-c5) во время Compute Phase. Если в этом регистре данные неправильно записаны, то будет выброшен 32 exit code.

### Action Phase | exit code = 33

В данный момент в одной транзакции может быть максимум `255` actions. Если это значение превышено, то Action Phase завершится с 33 exit code.

### Action Phase | exit code = 34

Данный exit code отвечает за большинство ошибок при работе с actions: невалидное сообщение, некорректный action и так далее.

### Action Phase | exit code = 35

Во время сборки [CommonMsgInfo](/develop/smart-contracts/tutorials/wallet#commonmsginfo) части сообщения необходимо указывать правильный source address. Он должен быть равен либо [addr_none](/develop/data-formats/msg-tlb#addr_none00), либо адресу аккаунта, который отправляет сообщение.

В коде блокчейна за это отвечает функция [check_replace_src_addr](https://github.com/ton-blockchain/ton/blob/9728bc65b75defe4f9dcaaea0f62a22f198abe96/crypto/block/transaction.cpp#L1985).

### Action Phase | exit code = 36

В случае, если destionation address невалидный, то выбрасывается 36 exit code. Некоторыми возможными причинами являются несуществующий workchain или некорректный адрес. Все проверки можно увидеть в функции [check_rewrite_dest_addr](https://github.com/ton-blockchain/ton/blob/9728bc65b75defe4f9dcaaea0f62a22f198abe96/crypto/block/transaction.cpp#L2014-L2113).

### Action Phase | exit code = 37

Данный exit code схож с `-14` в Compute Phase. Здесь он обозначает, что не хватает баланса для отправки указанного количества TON.

### Action Phase | exit code = 38

То же самое, что в `37` exit code, но относится к недостатку [ExtraCurrency](/develop/research-and-development/minter-flow#extracurrency) на балансе.

### Action Phase | exit code = 40

В случае, если TON хватает на обработку определённой части сообщения (допустим, 5 ячеек), а в сообщении - 10, выбрасывается 40 exit code.

### Action Phase | exit code = 43

Может возникнуть, if the maximum number of cells in the library is exceeded or the maximum depth of the Merkle tree is exceeded.

Library - это ячейка, которая хранится в [Masterchain](/learn/overviews/ton-blockchain#masterchain-blockchain-of-blockchains) и может использоваться всеми смарт контрактами, если она [публичная](https://github.com/ton-blockchain/ton/blob/9728bc65b75defe4f9dcaaea0f62a22f198abe96/crypto/block/transaction.cpp#L1844).

0 comments on commit d004e9c

Please sign in to comment.