User-friendly address: {userFriendlyAddress}
Raw address: {rawAddress}
@@ -314,7 +330,7 @@ await tonConnectUI.disconnect();
## Examples
* Step-by-step [TON Hello World guide](https://ton-community.github.io/tutorials/03-client/) to create a simple DAppwith React UI.
-* [Demo dApp](https://github.com/ton-connect/demo-dapp-with-react-ui) - Example of a DAppwith `@tonconnect/ui-react`.
+* [Demo dApp](https://github.com/ton-connect/demo-dapp-with-react-ui) - Example of a DApp with `@tonconnect/ui-react`.
* [ton.vote](https://github.com/orbs-network/ton-vote) - Example of React website with TON Connect implementation.
diff --git a/docs/develop/dapps/ton-connect/security.md b/docs/develop/dapps/ton-connect/security.md
index f487bc1a47..c9312b7686 100644
--- a/docs/develop/dapps/ton-connect/security.md
+++ b/docs/develop/dapps/ton-connect/security.md
@@ -8,5 +8,5 @@ TON Connect ensures that users have explicit control over the data they share, m
- Through TON Connect, security parameters are put in place to allow users data to be directly authenticated with their wallet address. This allows users to make use of multiple wallets and choose which one is used within a particular app.
- The TON Connect protocol allows for personal data item sharing (such as contact details and KYC info etc.) meaning the user explicitly confirms the sharing of such data.
-Specific details and related code examples pertaining to TON Connect and its underlying security-focused design can be found via [TON Connect Github](https://github.com/ton-connect/).
+Specific details and related code examples pertaining to TON Connect and its underlying security-focused design can be found via [TON Connect GitHub](https://github.com/ton-connect/).
diff --git a/docs/develop/dapps/ton-connect/sign.mdx b/docs/develop/dapps/ton-connect/sign.mdx
index 71c048bb08..adab4c33d4 100644
--- a/docs/develop/dapps/ton-connect/sign.mdx
+++ b/docs/develop/dapps/ton-connect/sign.mdx
@@ -1,18 +1,20 @@
import ThemedImage from '@theme/ThemedImage';
-# Signing and Verification
+# Verifying signed in users on backend
-## Use Cases
+This page describes a way for backend to ensure that the user truly owns the declared address.
+Please note that the user verification is not required for all DApps.
-Please note that signing is not required for all DApps. It will be useful if you want to verify a user to provide them with their personal information from the back end. This is necessary for authorization on the backend, to prove that the user truly owned the declared address.
+It is useful if you want to verify a user to provide them with their personal information from the back end.
+## How does it work?
-## How ton_proof Works?
-
-- Send DAppid to client. Typically, DAppid nested in the QR code.
-- Retrieve signed transaction with ton_proof entity
-- Verify ton_proof on the backend side
+- User initiates sign in process.
+- Backend generates a ton_proof entity and sends it to frontend.
+- Frontend signs in to wallet using ton_proof and receives back a signed ton_proof.
+- Frontend sends signed ton_proof to backend for verification.
+````mdx-code-block
-
+````
## Structure of ton_proof
-ton_proof works in TON Connect with a special `TonProof` entity, which implemented inside connector.
+We will be using the TonProof entity, implemented inside connector.
```js
type TonProofItemReply = TonProofItemReplySuccess | TonProofItemReplyError;
@@ -45,26 +47,21 @@ type TonProofItemReplySuccess = {
```
-## Check ton_proof with API
-
-1. Retrieve `TonProofItemReply` from user.
-2. Try to obtain public key via get_public_key get method on smart contract deployed at `address`
-3. If the smart contract has not been deployed (e.g., the user has just created a new wallet locally in the wallet app) or does not support get_public_key method(v3 contracts), follow these steps:
-* a. Parse wallet's StateInit `walletStateInit = TonAddressItemReply.walletStateInit`
-* b. Retrieve `{public_key, address}` from `walletStateInit` with [TON API](https://tonapi.io/) method POST /v2/tonconnect/stateinit
-* Check that `address` extracted from `walletStateInit` or corresponds to wallet's `address` declared by user.
-4. Verify timestamp, domain, signature with `public_key` (examples [GO](https://github.com/ton-connect/demo-dapp-backend/blob/master/proof.go), [TS](https://gist.github.com/TrueCarry/cac00bfae051f7028085aa018c2a05c6), [Python](https://github.com/XaBbl4/pytonconnect/blob/main/examples/check_proof.py))
-
-## How to Check TON Proof on Server Side
-
-Obtain from the frontend the following data: wallet address, domain, timestamp, walletStateInit, signature
-
-* Verify that the domain corresponds to the domain of your application
-* Check that this payload was issued recently (you can issue cookies with the payload before authorization, and when checking ton_proof, verify the presence of a cookie for this client)
-* Assemble a message according to the scheme from the previous slide
-* Obtain the wallet's pubkey via the wallet contract's get method
-* If the contract is not active, then obtaining the key in this manner will be impossible; you will need to parse the walletStateInit, which is provided by the frontend
-* Verify that the signature from the frontend actually signs the assembled message and corresponds to the public key of the address
+## Checking ton_proof on Server Side
+
+1. Retrieve `TonProofItemReply` from a user.
+2. Verify that the received domain corresponds to the domain of your application.
+3. Check if `TonProofItemReply.payload` is permitted by original server and is still active.
+4. Check if `timestamp` is actual at the moment.
+5. Assemble a message according to the [message scheme](/develop/dapps/ton-connect/sign#concept-explanation).
+6. Retrieve `public_key` either from API (a) or via back-end logic (b)
+- 6a:
+ - Retrieve `{public_key, address}` from the `walletStateInit` with [TON API](https://docs.tonconsole.com/tonapi/api-v2#:~:text=/v2/-,tonconnect,-/stateinit) method `POST /v2/tonconnect/stateinit`.
+ - Check that the `address` extracted from `walletStateInit` corresponds to wallet `address` declared by user.
+- 6b:
+ - Obtain the wallet `public_key` via the wallet contract [get method](https://github.com/ton-blockchain/wallet-contract/blob/main/func/wallet-v4-code.fc#L174).
+ - If the contract is not active, or if it lacks the get_method found in older wallet versions (v1-v3), then obtaining the key in this manner will be impossible. Instead, you will need to parse the walletStateInit provided by the frontend. Ensure that TonAddressItemReply.walletStateInit.hash() is equal to TonAddressItemReply.address.hash(), indicating a BoC hash.
+7. Verify that the `signature` from the frontend actually signs the assembled message and corresponds to the `public_key` of the address.
## React Example
@@ -82,7 +79,7 @@ function App() {
}
```
-2. Describe authentication for backend:
+2. Implement authentication on the frontend with backend integration:
Example
@@ -156,6 +153,60 @@ export function useBackendAuth() {
```
+
+
+## Backend Example
+
+
+Check if Proof Valid (Next.js)
+
+```tsx
+'use server'
+import {Address, Cell, contractAddress, loadStateInit, TonClient4} from '@ton/ton'
+
+
+export async function isValid(proof, account) {
+ const payload = {
+ address: account.address,
+ public_key: account.publicKey,
+ proof: {
+ ...proof,
+ state_init: account.walletStateInit
+ }
+ }
+ const stateInit = loadStateInit(Cell.fromBase64(payload.proof.state_init).beginParse())
+ const client = new TonClient4({
+ endpoint: 'https://mainnet-v4.tonhubapi.com'
+ })
+ const masterAt = await client.getLastBlock()
+ const result = await client.runMethod(masterAt.last.seqno, Address.parse(payload.address), 'get_public_key', [])
+ const publicKey = Buffer.from(result.reader.readBigNumber().toString(16).padStart(64, '0'), 'hex')
+ if (!publicKey) {
+ return false
+ }
+ const wantedPublicKey = Buffer.from(payload.public_key, 'hex')
+ if (!publicKey.equals(wantedPublicKey)) {
+ return false
+ }
+ const wantedAddress = Address.parse(payload.address)
+ const address = contractAddress(wantedAddress.workChain, stateInit)
+ if (!address.equals(wantedAddress)) {
+ return false
+ }
+ const now = Math.floor(Date.now() / 1000)
+ if (now - (60 * 15) > payload.proof.timestamp) {
+ return false
+ }
+ return true
+ }
+
+```
+
+
+You can review our [example](https://github.com/ton-connect/demo-dapp-with-react-ui/tree/master/src/server) showcasing the key methods:
+- [generatePayload](https://github.com/ton-connect/demo-dapp-with-react-ui/blob/master/src/server/api/generate-payload.ts): Generates a payload for ton proof
+- [checkProof](https://github.com/ton-connect/demo-dapp-with-react-ui/blob/master/src/server/api/check-proof.ts): Checks the proof and returns an access token.
+
## Concept Explanation
If `TonProofItem` is requested, wallet proves ownership of the selected account’s key. The signed message is bound to:
@@ -187,13 +238,13 @@ where:
* `Timestamp` 64-bit unix epoch time of the signing operation
* `Payload` is a variable-length binary string.
-Note: payload is variable-length untrusted data. To avoid using unnecessary length prefixes we put it last in the message.
+Note: payload is variable-length untrusted data. We put it last to avoid using unnecessary length prefixes.
The signature must be verified by public key:
1. First, try to obtain public key via `get_public_key` get-method on smart contract deployed at `Address`.
-2. If the smart contract is not deployed yet, or the get-method is missing, you need:
+2. If the smart contract is not deployed yet, or the get-method is missing, then:
1. Parse `TonAddressItemReply.walletStateInit` and get public key from stateInit. You can compare the `walletStateInit.code` with the code of standard wallets contracts and parse the data according to the found wallet version.
@@ -204,12 +255,15 @@ The signature must be verified by public key:
### Examples of TON Proof Verification
-* [GO demo app](https://github.com/ton-connect/demo-dapp-backend/blob/master/proof.go)
-* [TS example](https://gist.github.com/TrueCarry/cac00bfae051f7028085aa018c2a05c6)
+* [Go demo app](https://github.com/ton-connect/demo-dapp-backend)
+* [Rust demo app](https://github.com/liketurbo/demo-dapp-backend-rs)
+* [JS demo app](https://github.com/liketurbo/demo-dapp-backend-js)
* [Python example](https://github.com/XaBbl4/pytonconnect/blob/main/examples/check_proof.py)
+* [PHP example](https://github.com/vladimirfokingithub/Ton-Connect-Proof-Php-Check)
+* [C# demo app](https://github.com/WinoGarcia/TonProof.NET)
## See Also
* [[YouTube] Check ton_proof for @tonconnect/react-ui [RU]](https://youtu.be/wIMbkJHv0Fs?list=PLyDBPwv9EPsCJ226xS5_dKmXXxWx1CKz_&t=2971)
* [Preparing Messages](/develop/dapps/ton-connect/message-builders)
-* [Sending Messages](/develop/dapps/ton-connect/transactions)
\ No newline at end of file
+* [Sending Messages](/develop/dapps/ton-connect/transactions)
diff --git a/docs/develop/dapps/ton-connect/tg-bot-tonapi-nft.md b/docs/develop/dapps/ton-connect/tg-bot-tonapi-nft.md
index 01cfd082d3..52c16b0ca0 100644
--- a/docs/develop/dapps/ton-connect/tg-bot-tonapi-nft.md
+++ b/docs/develop/dapps/ton-connect/tg-bot-tonapi-nft.md
@@ -34,7 +34,7 @@ Our Telegram bot will perform the fascinating example task of verifying if a use
Execute the following command to install all the necessary libraries through `pip`:
```bash
-pip install aiogram redis qrcode tonsdk pytonconnect requests
+pip install aiogram redis qrcode pytoniq pytonconnect requests
```
And then, import them to the main file:
@@ -49,7 +49,7 @@ import random
from aiogram import Bot, Dispatcher, executor, types
from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton
from aiogram.types.input_file import InputFile
-from tonsdk.utils import Address
+from pytoniq import Address
from pytonconnect import TonConnect
```
@@ -240,7 +240,7 @@ async def connect_wallet_tonkeeper(message: types.Message):
await asyncio.sleep(1)
if connector.connected:
if connector.account.address:
- address = Address(connector.account.address).to_string(True, True, True)
+ address = Address(connector.account.address).to_str(True, True, True)
break
# Delete the previously sent QR code message
diff --git a/docs/develop/dapps/ton-connect/vue.mdx b/docs/develop/dapps/ton-connect/vue.mdx
new file mode 100644
index 0000000000..60792a6706
--- /dev/null
+++ b/docs/develop/dapps/ton-connect/vue.mdx
@@ -0,0 +1,482 @@
+# TON Connect for Vue
+
+Recommended SDK for Vue Apps is a [UI Vue SDK](/develop/dapps/ton-connect/developers#ton-connect-vue). It is a Vue component that provides a high-level way to interact with TON Connect.
+
+## Implementation
+
+### Installation
+
+To start integrating TON Connect into your DApp, you need to install the `@townsquarelabs/ui-vue` package. You can use npm or yarn for this purpose:
+
+```bash npm2yarn
+npm i @townsquarelabs/ui-vue
+```
+
+### TON Connect Initiation
+
+Add TonConnectUIProvider to the root of the app. You can specify UI options using props.
+
+
+All TonConnect UI hooks calls and `
` component must be placed inside `
`.
+
+```html
+
+
+
+
+
+
+
+```
+
+### Connect to the Wallet
+TonConnect Button is universal UI component for initializing connection. After wallet is connected it transforms to a wallet menu.
+It is recommended to place it in the top right corner of your app.
+
+```html
+
+
+
+
+
+```
+
+You can add `class` and `:style` props to the button as well. Note that you cannot pass child to the TonConnectButton.
+` `
+
+### Redirects
+
+If you want to redirect user to a specific page after wallet connection, you can use `useTonConnectUI` hook and [customize your return strategy](https://github.com/ton-connect/sdk/tree/main/packages/ui#add-the-return-strategy).
+
+#### Telegram Mini Apps
+
+If you want to redirect user to a [Telegram Mini App](/develop/dapps/telegram-apps/) after wallet connection, you can customize the `TonConnectUIProvider` element:
+
+```html
+
+
+
+
+
+
+
+```
+
+[Read more in SDK documentation](https://github.com/ton-connect/sdk/tree/main/packages/ui#use-inside-twa-telegram-web-app)
+
+### UI customization
+
+To [customize UI](https://github.com/ton-connect/sdk/tree/main/packages/ui#ui-customisation) of the modal you can use `useTonConnectUI` hook and `setOptions` function. See more about useTonConnectUI hook in [Hooks](#usetonconnectui) section.
+
+
+## Hooks
+
+### useTonAddress
+Use it to get user's current ton wallet address. Pass boolean parameter isUserFriendly to choose format of the address. If wallet is not connected hook will return empty string.
+
+```html
+
+
+ User-friendly address: {{ userFriendlyAddress }}
+ Raw address: {{ rawAddress }}
+
+
+
+
+```
+
+### useTonWallet
+Use it to get user's current ton wallet. If wallet is not connected hook will return null.
+
+See all wallet's properties
+// todo
+
+
+
+```html
+
+
+ Connected wallet: {{ wallet.name }}
+ Device: {{ wallet.device.appName }}
+
+
+
+
+```
+
+### useTonConnectModal
+
+Use this hook to access the functions for opening and closing the modal window. The hook returns an object with the current modal state and methods to open and close the modal.
+
+```html
+
+
+
Modal state: {{ state?.status }}
+
Open modal
+
Close modal
+
+
+
+
+```
+
+### useTonConnectUI
+Use it to get access to the `TonConnectUI` instance and UI options updating function.
+
+[See more about TonConnectUI instance methods](https://github.com/ton-connect/sdk/tree/main/packages/ui#send-transaction)
+
+[See more about setOptions function](https://github.com/ton-connect/sdk/tree/main/packages/ui#change-options-if-needed)
+
+
+```html
+
+
+
Send transaction
+
+ language
+
+ en
+ ru
+ zh
+
+
+
+
+
+
+```
+
+### useIsConnectionRestored
+Indicates current status of the connection restoring process.
+You can use it to detect when connection restoring process if finished.
+
+```html
+
+
+
+
+
+```
+
+
+## Usage
+
+Let's take a look at how to use the Vue UI SDK on practice.
+
+### Sending transactions
+
+Send TON coins (in nanotons) to a specific address:
+
+```html
+
+
+ Send transaction
+
+
+
+
+```
+### Understanding Transaction Status by Hash
+
+The principle located in Payment Processing (using tonweb). [See more](/develop/dapps/asset-processing/#checking-contracts-transactions)
+
+### Add connect request parameters (ton_proof)
+
+:::tip
+Understand how to sign and verify messages: [Signing and Verification](/develop/dapps/ton-connect/sign)
+:::
+
+Use `tonConnectUI.setConnectRequestParameters` function to pass your connect request parameters.
+
+This function takes one parameter:
+
+Set state to 'loading' while you are waiting for the response from your backend. If user opens connect wallet modal at this moment, he will see a loader.
+```ts
+import { ref } from 'vue';
+import { useTonConnectUI } from '@townsquarelabs/ui-vue';
+
+const tonConnectUI = useTonConnectUI();
+
+tonConnectUI.setConnectRequestParameters({
+ state: 'loading'
+});
+```
+
+or
+
+Set state to 'ready' and define `tonProof` value. Passed parameter will be applied to the connect request (QR and universal link).
+```ts
+import { ref } from 'vue';
+import { useTonConnectUI } from '@townsquarelabs/ui-vue';
+
+const tonConnectUI = useTonConnectUI();
+
+tonConnectUI.setConnectRequestParameters({
+ state: 'ready',
+ value: {
+ tonProof: ''
+ }
+});
+```
+
+or
+
+Remove loader if it was enabled via `state: 'loading'` (e.g. you received an error instead of a response from your backend). Connect request will be created without any additional parameters.
+```ts
+import { ref } from 'vue';
+import { useTonConnectUI } from '@townsquarelabs/ui-vue';
+
+const tonConnectUI = useTonConnectUI();
+
+tonConnectUI.setConnectRequestParameters(null);
+```
+
+
+You can call `tonConnectUI.setConnectRequestParameters` multiple times if your tonProof payload has bounded lifetime (e.g. you can refresh connect request parameters every 10 minutes).
+
+
+```ts
+import { ref } from 'vue';
+import { useTonConnectUI } from '@townsquarelabs/ui-vue';
+
+const tonConnectUI = useTonConnectUI();
+
+// enable ui loader
+tonConnectUI.setConnectRequestParameters({ state: 'loading' });
+
+// fetch you tonProofPayload from the backend
+const tonProofPayload: string | null = await fetchTonProofPayloadFromBackend();
+
+if (!tonProofPayload) {
+ // remove loader, connect request will be without any additional parameters
+ tonConnectUI.setConnectRequestParameters(null);
+} else {
+ // add tonProof to the connect request
+ tonConnectUI.setConnectRequestParameters({
+ state: "ready",
+ value: { tonProof: tonProofPayload }
+ });
+}
+
+```
+
+
+You can find `ton_proof` result in the `wallet` object when wallet will be connected:
+
+```ts
+import { ref, onMounted } from 'vue';
+import { useTonConnectUI } from '@townsquarelabs/ui-vue';
+
+const tonConnectUI = useTonConnectUI();
+
+onMounted(() =>
+ tonConnectUI.onStatusChange(wallet => {
+ if (wallet.connectItems?.tonProof && 'proof' in wallet.connectItems.tonProof) {
+ checkProofInYourBackend(wallet.connectItems.tonProof.proof, wallet.account);
+ }
+}));
+```
+
+### Wallet Disconnection
+
+Call to disconnect the wallet:
+```js
+import { useTonConnectUI } from '@townsquarelabs/ui-vue';
+
+const [tonConnectUI] = useTonConnectUI();
+
+await tonConnectUI.disconnect();
+```
+
+## Troubleshooting
+
+### Animations not working
+
+If you are experiencing issues with animations not working in your environment, it might be due to a lack of support for the Web Animations API. To resolve this issue, you can use the `web-animations-js` polyfill.
+
+#### Using npm
+
+To install the polyfill, run the following command:
+
+```shell
+npm install web-animations-js
+```
+
+Then, import the polyfill in your project:
+
+```typescript
+import 'web-animations-js';
+```
+
+#### Using CDN
+
+Alternatively, you can include the polyfill via CDN by adding the following script tag to your HTML:
+
+```html
+
+```
+
+Both methods will provide a fallback implementation of the Web Animations API and should resolve the animation issues you are facing.
+
+## Examples
+
+* [Demo dApp](https://github.com/TownSquareXYZ/demo-dapp-with-vue-ui) - Example of a DApp with `@townsquarelabs/ui-vue`.
diff --git a/docs/develop/dapps/ton-connect/wallet.mdx b/docs/develop/dapps/ton-connect/wallet.mdx
index a81bd46920..80e67f68f2 100644
--- a/docs/develop/dapps/ton-connect/wallet.mdx
+++ b/docs/develop/dapps/ton-connect/wallet.mdx
@@ -12,4 +12,10 @@ Use the following steps to connect your wallet to TON Connect:
2. Implement the protocol using one of the [SDKs](/develop/dapps/ton-connect/developers).
3. Add your wallet to the [wallets-list](https://github.com/ton-blockchain/wallets-list) with a pull request.
-Start Integration
+````mdx-code-block
+
+````
+Start Integration
+````mdx-code-block
+
+````
diff --git a/docs/develop/dapps/ton-connect/web.mdx b/docs/develop/dapps/ton-connect/web.mdx
index 5c744def5f..b9727411ad 100644
--- a/docs/develop/dapps/ton-connect/web.mdx
+++ b/docs/develop/dapps/ton-connect/web.mdx
@@ -7,9 +7,12 @@ This guide will help you integrate TON Connect into your Javascript application
If you use React for your DApp, take a look at [TON Connect UI React SDK](/develop/dapps/ton-connect/react).
+And if you use Vue for your DApp, take a look at [TON Connect UI Vue SDK](/develop/dapps/ton-connect/vue).
+
+
## Implementation
-### 1) Installation
+### Installation
@@ -31,7 +34,7 @@ npm i @tonconnect/ui
-### 2) TON Connect Initiation
+### TON Connect Initiation
After installing the package, you should create a `manifest.json` file for your application. More information on how to create a manifest.json file can be found [here](/develop/dapps/ton-connect/manifest).
@@ -52,7 +55,7 @@ Add a button with `ton-connect` id to connect to the wallet:
```
-### 3) Connect to the Wallet
+### Connect to the Wallet
"Connect" button (which is added at `buttonRootId`) automatically handles clicks.
@@ -73,11 +76,25 @@ But you can open "connect modal" programmatically, e.g. after click on custom bu
```
-### 4) Redirects
+### Redirects
+
+#### Customizing return strategy
+
+To redirect user to a specific URL after connection, you can [customize your return strategy](https://github.com/ton-connect/sdk/tree/main/packages/ui#add-the-return-strategy).
+
+#### Telegram Mini Apps
+
+To redirect user to a [Telegram Mini App](/develop/dapps/telegram-apps/) after wallet connection use `twaReturnUrl` option:
+
+```tsx
+tonConnectUI.uiOptions = {
+ twaReturnUrl: 'https://t.me/YOUR_APP_NAME'
+ };
+```
-Usually, you don't need to think about it at all. But if you want to redirect user to a specific page after wallet connection, you can [customize your return strategy](https://github.com/ton-connect/sdk/tree/main/packages/ui#add-the-return-strategy).
+[Read more in SDK documentation](https://github.com/ton-connect/sdk/tree/main/packages/ui#use-inside-twa-telegram-web-app)
-### 5) UI customization
+### UI customization
TonConnect UI provides an interface that should be familiar and recognizable to the user when using various apps. However, the app developer can make changes to this interface to keep it consistent with the app interface.
diff --git a/docs/develop/dapps/tutorials/accept-payments-in-a-telegram-bot-js.md b/docs/develop/dapps/tutorials/accept-payments-in-a-telegram-bot-js.md
index 83c5316de3..6082f26ec7 100644
--- a/docs/develop/dapps/tutorials/accept-payments-in-a-telegram-bot-js.md
+++ b/docs/develop/dapps/tutorials/accept-payments-in-a-telegram-bot-js.md
@@ -16,11 +16,11 @@ The bot will look like this:
## 📖 What you'll learn
You'll learn how to:
- - Create a Telegram bot in NodeJS using Grammy
+ - Create a Telegram bot in NodeJS using grammY
- Work with public TON Center API
-> Why do we use Grammy?
-Because Grammy is a modern, young, high-level framework for comfortable & fast development of telegram bots on JS/TS/Deno, in addition to this Grammy has great [documentation](https://grammy.dev) and an active community that can always help you.
+> Why do we use grammY?
+Because grammY is a modern, young, high-level framework for comfortable & fast development of telegram bots on JS/TS/Deno, in addition to this grammY has great [documentation](https://grammy.dev) and an active community that can always help you.
## ✍️ What you need to get started
diff --git a/docs/develop/dapps/tutorials/building-web3-game.md b/docs/develop/dapps/tutorials/building-web3-game.md
new file mode 100644
index 0000000000..13012ce408
--- /dev/null
+++ b/docs/develop/dapps/tutorials/building-web3-game.md
@@ -0,0 +1,275 @@
+# TON blockchain for games
+
+## What’s in the tutorial
+In this tutorial we will consider how to add the TON blockchain to a game. For our example, we will use a Flappy Bird clone written in Phaser and will add GameFi features step by step. In the tutorial we will use short code pieces and pseudocode to make it more readable. Also, we will provide links to real code blocks to help you understand better. The whole implementation can be found in the [demo repo](https://github.com/ton-community/flappy-bird).
+
+![Flappy Bird game without GameFi features](/img/tutorials/gamefi-flappy/no-gamefi-yet.png)
+
+We are going to implement the following:
+- Achievements. Let’s reward our users with [SBTs](https://docs.ton.org/learn/glossary#sbt). The achievement system is a great tool to increase user engagement.
+- Game currency. In TON blockchain it’s easy to launch your own token (jetton). The token can be used to create an in-game economy. Our users will be able to earn the game coins to spend them later.
+- Game shop. We will provide users with the possibility to purchase in-game items using either in-game currency or the TON coin itself.
+
+## Preparations
+
+### Install GameFi SDK
+First, we will set up the game environment. To do that we need to install `assets-sdk`. The package is designed to prepare everything developers need to integrate the blockchain into games. The lib can be used either from CLI or from Node.js scripts. In this tutorial we stick with the CLI approach.
+```sh
+npm install -g @ton-community/assets-sdk@beta
+```
+
+### Create a master wallet
+Next, we need to create a master wallet. The master wallet is a wallet we will use to mint the jetton, collections, NFTs, SBTs and receive payments.
+```sh
+assets-cli setup-env
+```
+You will be asked a few questions:
+
+Field | Hint
+:----- | :-----
+Network | Select `testnet` as far it’s a test game.
+Type | Select `highload-v2`type of wallet as far it’s the best, performant option to use as a master wallet.
+Storage | The storage will be used to store `NFT`/`SB`T files. `Amazon S3` (centralized) or `Pinata` (decentralized). For the tutorial let’s use `Pinata` as far as decentralized storage will be more illustrative for the Web3 game.
+IPFS gateway | Service to load assets metadata from: `pinata`, `ipfs.io` or enter other service URL.
+
+The script outputs the link you can open to see the created wallet state.
+
+![New wallet in Nonexist status](/img/tutorials/gamefi-flappy/wallet-nonexist-status.png)
+
+As you can see the wallet is not actually created yet. To the wallet be really created we need to deposit some funds into it. In the real-world scenario, you can deposit the wallet any way you prefer using the wallet address. In our case we will use [Testgiver TON Bot](https://t.me/testgiver_ton_bot). Please open it to claim 5 test TON coins.
+
+A bit later you could see 5 TON on the wallet and its status became `Uninit`. The wallet is ready. After the first usage it changes status to `Active`.
+
+![Wallet status after top-up](/img/tutorials/gamefi-flappy/wallet-nonexist-status.png)
+
+### Mint in-game currency
+We are going to create in-game currency to reward users with it:
+```sh
+assets-cli deploy-jetton
+```
+You will be asked a few questions:
+
+Field | Hint
+:----- | :-----
+Name | Token name, for example ` Flappy Jetton `.
+Description | Token description, for instance: A vibrant digital token from the Flappy Bird universe.
+Image | Download prepared [jetton logo](https://raw.githubusercontent.com/ton-community/flappy-bird/ca4b6335879312a9b94f0e89384b04cea91246b1/scripts/tokens/flap/image.png) and specify file path. Of course, you can use any image.
+Symbol | `FLAP` or enter any abbreviation you want to use.
+Decimals | How many zeros after the dot your currency will have. Let’ it be `0` in our case.
+
+The script outputs the link you can open to see the created jetton state. It will have `Active` status. The wallet status will change the status from `Uninit` to `Active`.
+
+![In-game currency / jetton](/img/tutorials/gamefi-flappy/jetton-active-status.png)
+
+### Create collections for SBTs
+Just for example, in the demo game we will reward users for the first and the fifth games. So, we will mint two collections to put SBTs into them when users achieve related conditions – play first and fifth time:
+```sh
+assets-cli deploy-nft-collection
+```
+
+Field | First game | Fifth game
+:----- | :----- | :-----
+Type | `sbt` | `sbt`
+Name | Flappy First Flight | Flappy High Fiver
+Description | Commemorating your inaugural journey in the Flappy Bird game! | Celebrate your persistent play with the Flappy High Fiver NFT!
+Image | You can download [the image](https://raw.githubusercontent.com/ton-community/flappy-bird/article-v1/scripts/tokens/first-time/image.png) here | You can download [the image](https://raw.githubusercontent.com/ton-community/flappy-bird/article-v1/scripts/tokens/five-times/image.png) here
+
+We are fully prepared. So, let’s go to the logic implementation.
+
+## Connecting wallet
+Everything starts from a user connects his wallet. So, let’s add wallet connect integration. To work with the blockchain from the client side we need to install GameFi SDK for Phaser:
+```sh
+npm install --save @ton/phaser-sdk@beta
+```
+Now let’s setup GameFi SDK and create an instance of it:
+```typescript
+import { GameFi } from '@ton/phaser-sdk'
+
+const gameFi = await GameFi.create({
+ network: 'testnet'
+ connector: {
+ // if tonconnect-manifest.json is placed in the root you can skip this option
+ manifestUrl: '/assets/tonconnect-manifest.json',
+ actionsConfiguration: {
+ // address of your Telegram Mini App to return to after the wallet is connected
+ // url you provided to BothFather during the app creation process
+ // to read more please read https://github.com/ton-community/flappy-bird#telegram-bot--telegram-web-app
+ twaReturnUrl: URL_YOU_ASSIGNED_TO_YOUR_APP
+ },
+ contentResolver: {
+ // some NFT marketplaces don't support CORS, so we need to use a proxy
+ // you are able to use any format of the URL, %URL% will be replaced with the actual URL
+ urlProxy: `${YOUR_BACKEND_URL}/${PROXY_URL}?url=%URL%`
+ },
+ // where in-game purchases come to
+ merchant: {
+ // in-game jetton purchases (FLAP)
+ // use address you got running `assets-cli deploy-jetton`
+ jettonAddress: FLAP_ADDRESS,
+ // in-game TON purchases
+ // use master wallet address you got running `assets-cli setup-env`
+ tonAddress: MASTER_WALLET_ADDRESS
+ }
+ },
+
+})
+```
+> To learn more about initialization options please read the [library documentation](https://github.com/ton-org/game-engines-sdk).
+
+> To learn what `tonconnect-manifest.json` is please check ton-connect [manifest description](https://docs.ton.org/develop/dapps/ton-connect/manifest).
+
+Now we are ready to create a wallet connect button. Let’s create a UI scene in Phaser which will contain the connect button:
+```typescript
+class UiScene extends Phaser.Scene {
+ // receive gameFi instance via constructor
+ private gameFi: GameFi;
+
+ create() {
+ this.button = this.gameFi.createConnectButton({
+ scene: this,
+ // you can calculate the position for the button in your UI scene
+ x: 0,
+ y: 0,
+ button: {
+ onError: (error) => {
+ console.error(error)
+ }
+ // other options, read the docs
+ }
+ })
+ }
+}
+```
+
+> Read how to create [connect button](https://github.com/ton-community/flappy-bird/blob/article-v1/workspaces/client/src/connect-wallet-ui.ts#L82) and the [UI scene](https://github.com/ton-community/flappy-bird/blob/article-v1/workspaces/client/src/connect-wallet-ui.ts#L45).
+
+To watch when a user connects or disconnects his wallet let’s use the following piece of code:
+```typescript
+function onWalletChange(wallet: Wallet | null) {
+ if (wallet) {
+ // wallet is ready to use
+ } else {
+ // wallet is disconnected
+ }
+}
+const unsubscribe = gameFi.onWalletChange(onWalletChange)
+```
+
+> To learn about more complex scenarios please check out the full implementation of [wallet connect flow](https://github.com/ton-community/flappy-bird/blob/article-v1/workspaces/client/src/index.ts#L16).
+
+Read how [game UI managing](https://github.com/ton-community/flappy-bird/blob/article-v1/workspaces/client/src/index.ts#L50) might be implemented.
+
+Now we have the user wallet connected and we can move forward.
+
+![Connect wallet button](/img/tutorials/gamefi-flappy/wallet-connect-button.png)
+![Confirm wallet connection](/img/tutorials/gamefi-flappy/wallet-connect-confirmation.png)
+![Wallet is connected](/img/tutorials/gamefi-flappy/wallet-connected.png)
+
+
+## Implementing achievements & rewards
+To implement achievements and reward system we need to prepare an endpoint which will be requested per user try.
+
+### `/played` endpoint
+We need to create an endpoint `/played ` which must do the following:
+- receive a body with a user wallet address and Telegram initial data passed to Mini App during the app launch. The initial data needs to be parsed to extract authentication data and ensure a user sends the request only on its behalf.
+- the endpoint must calculate and store the number of games a user played.
+- the endpoint must check if it’s the first or fifth game for a user and if so, reward a user with related SBT.
+- the endpoint must reward a user with 1 FLAP for each game.
+
+> Read [/played endpoint](https://github.com/ton-community/flappy-bird/blob/article-v1/workspaces/server/src/index.ts#L197) code.
+
+### Request `/played` endpoint
+Every time the bird hits a pipe or falls down the client code must call `/played` endpoint passing the correct body:
+```typescript
+async function submitPlayed(endpoint: string, walletAddress: string) {
+ return await (await fetch(endpoint + '/played', {
+ body: JSON.stringify({
+ tg_data: (window as any).Telegram.WebApp.initData,
+ wallet: walletAddress
+ }),
+ headers: {
+ 'content-type': 'application/json'
+ },
+ method: 'POST'
+ })).json()
+}
+
+const playedInfo = await submitPlayed('http://localhost:3001', wallet.account.address);
+```
+
+> Read [submitPlayer function](https://github.com/ton-community/flappy-bird/blob/article-v1/workspaces/client/src/game-scene.ts#L10) code.
+
+Let’s play the first time and ensure we will be rewarded with a FLAP token and SBT. Click the Play button, fly through a pipe or two and then hit into a tube. Alright, everything works!
+
+![Rewarded with token and SBT](/img/tutorials/gamefi-flappy/sbt-rewarded.png)
+
+Play 4 more times to get the second SBT, then open your Wallet, TON Space. Here your collectibles are:
+
+![Achievements as SBT in Wallet](/img/tutorials/gamefi-flappy/sbts-in-wallet.png)
+
+## Implementing game shop
+To have an in-game shop we need to have two components. The first is an endpoint that provides info about users purchases. The second is a global loop to watch user transactions and assign game properties to its owners.
+
+### `/purchases` endpoint
+The endpoint does the following:
+- receive `auth` get param with Telegram Mini Apps initial data.
+- the endpoint gets items a user purchased and responds with the items list.
+
+> Read [/purchases](https://github.com/ton-community/flappy-bird/blob/article-v1/workspaces/server/src/index.ts#L303) endpoint code.
+
+### Purchases loop
+To know when users make payments, we need to watch the master wallet transactions. Every transaction must contain a message `userId`:`itemId`. We will remember the last processed transaction, get only new ones, assign users properties they bought using `userId` and `itemId`, rewrite the last transaction hash. This will work in an infinite loop.
+
+> Read [purchase loop](https://github.com/ton-community/flappy-bird/blob/article-v1/workspaces/server/src/index.ts#L110) code.
+
+### Client side for the shop
+
+On the client side we have the Shop button.
+
+![Enter shop button](/img/tutorials/gamefi-flappy/shop-enter-button.png)
+
+When a user clicks the button, the shop scene is opened. The shop scene contains the list of items a user can buy. Each item has a price and a Buy button. When a user clicks the Buy button, the purchase is made.
+
+Opening the Shop will trigger purchased items loading and updating it every 10 seconds:
+```typescript
+// inside of fetchPurchases function
+await fetch('http://localhost:3000/purchases?auth=' + encodeURIComponent((window as any).Telegram.WebApp.initData))
+// watch for purchases
+setTimeout(() => { fetchPurchases() }, 10000)
+```
+
+> Read [showShop function](https://github.com/ton-community/flappy-bird/blob/article-v1/workspaces/client/src/ui.ts#L191) code.
+
+Now we need to implement the purchase itself. To do that, we will create GameFi SDK instance first and then use `buyWithJetton` method:
+```typescript
+gameFi.buyWithJetton({
+ amount: BigInt(price),
+ forwardAmount: BigInt(1),
+ forwardPayload: (window as any).Telegram.WebApp.initDataUnsafe.user.id + ':' + itemId
+});
+```
+
+![Game prop to purchase](/img/tutorials/gamefi-flappy/purchase-item.png)
+![Purchase confirmation](/img/tutorials/gamefi-flappy/purchase-confirmation.png)
+![Property is ready to use](/img/tutorials/gamefi-flappy/purchase-done.png)
+
+It's also possible to pay with the TON coin:
+```typescript
+import { toNano } from '@ton/phaser-sdk'
+
+gameFi.buyWithTon({
+ amount: toNano(0.5),
+ comment: (window as any).Telegram.WebApp.initDataUnsafe.user.id + ':' + 1
+});
+```
+
+## Afterword
+
+That’s it for this tutorial! We considered the basic GameFi features, but the SDK delivers more functionality like transfers between players, utils to work NFTs and collections, etc. We will deliver even more features in the future.
+
+To learn about all the GameFi features you can use read the docs of [ton-org/game-engines-sdk](https://github.com/ton-org/game-engines-sdk) and [@ton-community/assets-sdk](https://github.com/ton-community/assets-sdk).
+
+So, let us know what you think in the [Discussions](https://github.com/ton-org/game-engines-sdk/discussions)!
+
+
+The complete implementation is available in [flappy-bird](https://github.com/ton-community/flappy-bird) repo.
diff --git a/docs/develop/dapps/tutorials/collection-minting.md b/docs/develop/dapps/tutorials/collection-minting.md
index 11e040534e..8b0149144a 100644
--- a/docs/develop/dapps/tutorials/collection-minting.md
+++ b/docs/develop/dapps/tutorials/collection-minting.md
@@ -36,7 +36,7 @@ The implementation of the NFT in ETH is extremely simple - there is 1 main contr
### Problems that can occur with such implementation in TON
-The problems of such an implementation in the context of TON are perfectly described by the [NFT standart](https://github.com/ton-blockchain/TEPs/blob/master/text/0062-nft-standard.md) in TON:
+The problems of such an implementation in the context of TON are perfectly described by the [NFT standard](https://github.com/ton-blockchain/TEPs/blob/master/text/0062-nft-standard.md) in TON:
* Unpredictable gas consumption. In TON, gas consumption for dictionary operations depends on exact set of keys. Also, TON is an asynchronous blockchain. This means that if you send a message to a smart contract, then you do not know how many messages from other users will reach the smart contract before your message. Thus, you do not know what the size of the dictionary will be at the moment when your message reaches the smart contract. This is OK with a simple wallet -> NFT smart contract interaction, but not acceptable with smart contract chains, e.g. wallet -> NFT smart contract -> auction -> NFT smart contract. If we cannot predict gas consumption, then a situation may occur like that the owner has changed on the NFT smart contract, but there were no enough Toncoins for the auction operation. Using smart contracts without dictionaries gives deterministic gas consumption.
@@ -51,7 +51,7 @@ In TON we have 1 master contract - smart-contract of our collection, that store
![](/img/tutorials/nft/ton-collection.png)
:::info
-You can check [NFT processing on TON](/develop/dapps/asset-processing/nfts) article or read [NFT standart](https://github.com/ton-blockchain/TEPs/blob/master/text/0062-nft-standard.md) if you want to dive deeper into this topic
+You can check [NFT processing on TON](/develop/dapps/asset-processing/nfts) article or read [NFT standard](https://github.com/ton-blockchain/TEPs/blob/master/text/0062-nft-standard.md) if you want to dive deeper into this topic
:::
## ⚙ Setup development environment
@@ -104,7 +104,7 @@ PINATA_API_SECRET=your_secret_api_key
MNEMONIC=word1 word2 word3 word4
TONCENTER_API_KEY=aslfjaskdfjasasfas
```
-You can get toncenter api key from [@tontestnetapibot](https://t.me/@tontestnetapibot) ([@tonapibot](https://t.me/@tonapibot) for mainnet). In `MNEMONIC` variable store 24 words of collection owner wallet seed phrase.
+You can get toncenter api key from [@tonapibot](https://t.me/tonapibot) and choose mainnet or testnet. In `MNEMONIC` variable store 24 words of collection owner wallet seed phrase.
Great! Now we are ready to start writing code for our project.
@@ -221,7 +221,7 @@ Based on this info, let's create our own metadata file `collection.json`, that w
```json
{
"name": "Ducks on TON",
- "description": "This collection is created for showing an example of minting NFT collection on TON. You can support creator by bying one of this NFT.",
+ "description": "This collection is created for showing an example of minting NFT collection on TON. You can support creator by buying one of this NFT.",
"social_links": ["https://t.me/DucksOnTON"]
}
```
@@ -284,7 +284,7 @@ This is really inconvenient and wrong, so let's write a function that will do th
export async function updateMetadataFiles(metadataFolderPath: string, imagesIpfsHash: string): Promise {
const files = readdirSync(metadataFolderPath);
- files.forEach(async (filename, index) => {
+ await Promise.all(files.map(async (filename, index) => {
const filePath = path.join(metadataFolderPath, filename)
const file = await readFile(filePath);
@@ -295,7 +295,7 @@ export async function updateMetadataFiles(metadataFolderPath: string, imagesIpfs
: `ipfs://${imagesIpfsHash}/logo.jpg`;
await writeFile(filePath, JSON.stringify(metadata));
- });
+ }));
}
```
Here we firstly read all of the files in specified folder:
@@ -478,7 +478,7 @@ commonContentUrl | Base url for NFT items metadata
Firstly let's write private method, that will return cell with code of our collection.
```ts
-export class Collection {
+export class NftCollection {
private collectionData: collectionData;
constructor(collectionData: collectionData) {
@@ -693,12 +693,12 @@ Great! Now we can comeback to `NftItem.ts`. All we have to do is just send messa
```ts
import { internal, SendMode } from "ton-core";
import { OpenedWallet } from "utils";
-import { Collection, mintParams } from "./NftCollection";
+import { NftCollection, mintParams } from "./NftCollection";
export class NftItem {
- private collection: Collection;
+ private collection: NftCollection;
- constructor(collection: Collection) {
+ constructor(collection: NftCollection) {
this.collection = collection;
}
@@ -1043,6 +1043,36 @@ msgBody.storeBit(0); // no forward_payload
return msgBody.endCell();
```
+And create a transfer function to transfer the NFT.
+
+```ts
+static async transfer(
+ wallet: OpenedWallet,
+ nftAddress: Address,
+ newOwner: Address
+ ): Promise {
+ const seqno = await wallet.contract.getSeqno();
+
+ await wallet.contract.sendTransfer({
+ seqno,
+ secretKey: wallet.keyPair.secretKey,
+ messages: [
+ internal({
+ value: "0.05",
+ to: nftAddress,
+ body: this.createTransferBody({
+ newOwner,
+ responseTo: wallet.contract.address,
+ forwardAmount: toNano("0.02"),
+ }),
+ }),
+ ],
+ sendMode: SendMode.IGNORE_ERRORS + SendMode.PAY_GAS_SEPARATELY,
+ });
+ return seqno;
+ }
+```
+
Nice, now we can we are already very close to the end. Back to the `app.ts` and let's get address of our nft, that we want to put on sale:
```ts
const nftToSaleAddress = await NftItem.getAddressByIndex(collection.address, 0);
@@ -1081,16 +1111,16 @@ Now we can launch our project and enjoy the process!
```
yarn start
```
-Go to https://testnet.getgems.io/YOUR_COLLECTION_ADDRESS_HERE and look to this perfect ducks!
+Go to https://testnet.getgems.io/collection/ and look to this perfect ducks!
## Conclusion
-Today you have learned a lot of new things about TON and even created your own beautiful NFT collection in the testnet! If you still have any questions or have noticed an error - feel free to write to the author - [@coalus](https:/t.me/coalus)
+Today you have learned a lot of new things about TON and even created your own beautiful NFT collection in the testnet! If you still have any questions or have noticed an error - feel free to write to the author - [@coalus](https://t.me/coalus)
## References
-- [GetGems NFT-contracts](https:/github.com/getgems-io/nft-contracts)
-- [NFT Standart](https://github.com/ton-blockchain/TEPs/blob/master/text/0062-nft-standard.md)
+- [GetGems NFT-contracts](https://github.com/getgems-io/nft-contracts)
+- [NFT Standard](https://github.com/ton-blockchain/TEPs/blob/master/text/0062-nft-standard.md)
## About the author
-- Coalus on [Telegram](https:/t.me/coalus) or [Github](https:/github.com/coalus)
+- Coalus on [Telegram](https://t.me/coalus) or [GitHub](https://github.com/coalus)
diff --git a/docs/develop/dapps/tutorials/how-to-run-ton-site.md b/docs/develop/dapps/tutorials/how-to-run-ton-site.md
index b72e10714a..74c4b2c50a 100644
--- a/docs/develop/dapps/tutorials/how-to-run-ton-site.md
+++ b/docs/develop/dapps/tutorials/how-to-run-ton-site.md
@@ -12,8 +12,8 @@ Install [Tonutils Reverse Proxy](https://github.com/tonutils/reverse-proxy) to u
##### Download
```bash
-wget https://github.com/ton-utils/reverse-proxy/releases/download/v0.2.0/tonutils-reverse-proxy-linux-amd64
-chmod 777 tonutils-reverse-proxy-linux-amd64
+wget https://github.com/ton-utils/reverse-proxy/releases/latest/download/tonutils-reverse-proxy-linux-amd64
+chmod +x tonutils-reverse-proxy-linux-amd64
```
##### Run
@@ -54,4 +54,8 @@ You can check the availability of the site by opening this address with the doma
* [TON Sites, TON WWW and TON Proxy](https://blog.ton.org/ton-sites)
* [Tonutils Reverse Proxy](https://github.com/tonutils/reverse-proxy)
- * Authors: [Andrew Burnosov](https://github.com/AndreyBurnosov) (TG: [@AndrewBurnosov](https://t.me/AndreyBurnosov)), [Daniil Sedov](https://gusarich.com) (TG: [@sedov](https://t.me/sedov)), [George Imedashvili](https://github.com/drforse)
+ * Authors: [Andrew Burnosov](https://github.com/AndreyBurnosov) (TG: [@AndrewBurnosov](https://t.me/AndreyBurnosov)), [Daniil Sedov](https://gusarich.com) (TG: [@sedov](https://t.me/sedov)), [George Imedashvili](https://github.com/drforse)
+
+
+## See Also
+* [Run C++ Implementation](/participate/web3/sites-and-proxy)
diff --git a/docs/develop/dapps/tutorials/jetton-minter.md b/docs/develop/dapps/tutorials/jetton-minter.md
index 5c21532948..fb7ca4ea90 100644
--- a/docs/develop/dapps/tutorials/jetton-minter.md
+++ b/docs/develop/dapps/tutorials/jetton-minter.md
@@ -58,7 +58,7 @@ If you want to have an attractive Jetton token, you need a beautiful logo hosted
* https://bitcoincash-example.github.io/website/logo.png
:::info
- You can easily find out about about url placement of the logo in the [repository](https://github.com/ton-blockchain/minter-contract#jetton-metadata-field-best-practices) in paragraph "Where is this metadata stored".
+ You can easily find out about url placement of the logo in the [repository](https://github.com/ton-blockchain/minter-contract#jetton-metadata-field-best-practices) in paragraph "Where is this metadata stored".
* On-chain.
* Off-chain IPFS.
@@ -213,3 +213,4 @@ If you want to go deeper, read this article by Tal Kol:
- Project: https://github.com/ton-blockchain/minter-contract
- By Slava ([Telegram @delovoyslava](https://t.me/delovoyslava), [delovoyhomie on GitHub](https://github.com/delovoyhomie))
+ - [Jetton processing](/develop/dapps/asset-processing/jettons)
diff --git a/docs/develop/dapps/tutorials/send-transactions-from-highload.md b/docs/develop/dapps/tutorials/send-transactions-from-highload.md
new file mode 100644
index 0000000000..9c085c787c
--- /dev/null
+++ b/docs/develop/dapps/tutorials/send-transactions-from-highload.md
@@ -0,0 +1,155 @@
+# Highload Wallet v3 Transaction Guide
+
+## Purpose and Goals 🎯
+
+The purpose of this guide is to provide a comprehensive set of instructions for sending transactions using Highload Wallet v3. The goal is to help developers and users understand how to deploy contracts, send messages, and track transactions using the provided Python scripts. This guide assumes you have the necessary API keys and mnemonics set up.
+
+## Prerequisites 🛠️
+
+Before you start, make sure you have the following:
+- Python environment with `pytoniq` installed.
+- API key for accessing the TON Center API.
+- Mnemonics for your Highload Wallet.
+- Recipient address for test transactions.
+
+## Installation 📦
+
+Install the required package using pip:
+```sh
+pip install pytoniq
+```
+
+## Code Snippets and Instructions 📄
+
+### 1. Setup API Endpoints and Utility Functions 🌐
+
+Define the endpoints and utility functions for making API requests.
+```python
+import requests
+
+api_key = "..." # PLACE API KEY HERE
+
+api_v2_endpoint = "https://toncenter.com/api/v2/jsonRPC"
+
+def api_v2_request(method, api_key=None, **params):
+ headers = {"X-Api-Key": api_key} if api_key else None
+ payload = {"id": 1, "jsonrpc": 2.0, "method": method, "params": params}
+ resp = requests.post(api_v2_endpoint, headers=headers, json=payload)
+ if resp.status_code == 200:
+ return resp.json()["result"]
+ raise RuntimeError(resp.json()["error"])
+
+send_boc_endpoint = "https://toncenter.com/api/v2/sendBocReturnHash"
+
+def send_boc_request(address, boc, api_key=None):
+ headers = {"X-Api-Key": api_key} if api_key else None
+ payload = {"boc": boc}
+ params = {"address": address}
+ resp = requests.post(
+ send_boc_endpoint, params=params, headers=headers, json=payload
+ )
+ if resp.status_code == 200:
+ return resp.json()["result"]
+ raise RuntimeError(resp.json()["error"])
+
+api_v3_endpoint = "https://toncenter.com/api/v3"
+
+def api_v3_request(method, api_key=None, **params):
+ headers = {"X-Api-Key": api_key} if api_key else None
+ resp = requests.get(f"{api_v3_endpoint}/{method}", headers=headers, params=params)
+ if resp.status_code == 200:
+ return resp.json()
+ raise RuntimeError(resp.json()["error"])
+```
+
+### 2. Setup Wallet and Generate Address 🔑
+
+Set up your wallet using mnemonics and generate the raw address.
+```python
+from pytoniq import liteclient, WalletV4, LiteClientLike, LiteClient
+import asyncio
+
+
+async def main():
+ client = LiteClient.from_mainnet_config( # choose mainnet, testnet or custom config dict
+ ls_i=0, # index of liteserver from config
+ trust_level=2, # trust level to liteserver
+ timeout=15 # timeout not includes key blocks synchronization as it works in pytonlib
+ )
+
+ await client.connect()
+
+ wallet: WalletV4 = await WalletV4.from_mnemonic(client, [
+ 'casual', 'doctor', 'across',
+ 'later', 'pledge', 'burden',
+ 'desert', 'remain', 'under',
+ 'moment', 'meat', 'define',
+ 'relief', 'tennis', 'sphere',
+ 'tattoo', 'long', 'manual',
+ 'fiction', 'push', 'couch',
+ 'wink', 'behind', 'crumble'
+ ])
+
+ address: str = wallet.address.to_str(True, True, True)
+ print(address)
+
+
+asyncio.run(main())
+
+```
+
+### 3. Deploy Contract 📜
+
+Create and deploy the contract. You **must send some TONs to the address** before calling this function. You can get address by running previous or current function.
+```python
+async def init_contract(wallet_v3r2: WalletV4):
+ # send some tons (0.1) to the address before calling init_external function
+ address: str = wallet_v3r2.address.to_str(True, True, True)
+ print(address)
+
+ print(wallet_v3r2.state.code.get_depth())
+ response = await wallet_v3r2.send_init_external()
+```
+
+### 4. Create and Send Transactions 💸
+
+Prepare and send transactions to multiple recipients.
+```python
+async def send_tons(wallet_v3r2: WalletV4, target: typing.Union[str, pytoniq.Address], amount: int):
+ cell = pytoniq.begin_cell().store_int(20, 8).end_cell()
+ response = await wallet_v3r2.transfer(target), amount)
+ print(response)
+
+
+async def send_tons_multi_target(wallet: HighloadWallet, targets: typing.Union[typing.List[str], typing.List[pytoniq.Address]], amounts: typing.List[int]):
+ cell = pytoniq.begin_cell().end_cell()
+ response = await wallet.transfer(targets, amounts, [cell])
+ print(response)
+```
+
+### 5. Wait for Transaction Confirmation ⏳
+
+Wait for the transaction to be confirmed.
+```python
+# scan blockchain for transaction
+async def wait_for_transaction(client: LiteClient, number: int = 20):
+ # logic depends on you transaction creating process
+ while True:
+ # You can scan for message hashes if you save them instead of using these "additional" numbers
+ responses = await client.get_transactions('', 10)
+ for response in responses:
+ transaction: pytoniq_core.Transaction = response
+ # We saved 20 into the body before sending
+ if transaction.in_msg.body.begin_parse().load_int(8) == number:
+ break
+ else:
+ await asyncio.sleep(1)
+ continue
+
+ break
+ return
+```
+
+---
+
+This guide covers the essential steps for sending transactions from a Highload Wallet v3. Make sure to replace placeholders with your actual API keys, mnemonics, and addresses to execute the scripts successfully. Happy coding! 🚀
diff --git a/docs/develop/dapps/tutorials/simple-zk-on-ton.md b/docs/develop/dapps/tutorials/simple-zk-on-ton.md
index 61feaf8400..b8576a534d 100644
--- a/docs/develop/dapps/tutorials/simple-zk-on-ton.md
+++ b/docs/develop/dapps/tutorials/simple-zk-on-ton.md
@@ -1,56 +1,52 @@
-# Simple Zero-Knowledge project on TON
-
-Welcome to the simple Zero-Knowledge project on TON tutorial. In this tutorial, we will learn about Zero-Knowledge proofs and how to use them in TON.
+# Building a simple ZK project on TON
## 👋 Introduction
-**Zero-knowledge** proofs are a fundamental cryptographic primitive that allows one party (the prover) to prove to another (the verifier) that a statement is true, without revealing any information beyond the validity of the statement itself. Zero-knowledge proofs are a powerful tool for building privacy-preserving systems, and have been used in a variety of applications, including anonymous payments, anonymous messaging, and trustless-bridges.
+**Zero-knowledge** (ZK) proofs are a fundamental cryptographic primitive that allows one party (the prover) to prove to another party (the verifier) that a statement is true without revealing any information beyond the validity of the statement itself. Zero-knowledge proofs are a powerful tool for building privacy-preserving systems and have been used in a variety of applications including anonymous payments, anonymous messaging systems, and trustless bridges.
-:::tip TVM June 2023 update
-Before June 2023 it wasn't possible to verify proofs on TON. Due to complex computation behind the pairing algorithm, we needed TVM Opcodes for these operation which were added in [June 2023 update](https://docs.ton.org/learn/tvm-instructions/tvm-upgrade#bls12-381)(Only available on testnet for now).
+:::tip TVM Upgrade 2023.07
+Prior to June 2023 it wasn't possible to verify cryptographic proofs on TON. Due to the prevalence of complex computation behind the pairing algorithm, it was necessary to increase the functionality of TVM by adding TVM opcodes to conduct proof verification. This functionality was added in the [June 2023 update](https://docs.ton.org/learn/tvm-instructions/tvm-upgrade#bls12-381) and at the time of this writing is only available on testnet.
:::
-## 🦄 What you will learn
-1. You will learn about ZK and specifically zk-SNARK(Zero-knowledge Succinct Non-Interactive ARgument of Knowledge)
-2. You will learn to do a trusted setup ceremony(Powers of Tau)
-3. You will write and compile a simple ZK circuit(Circom language)
-4. You will generate and deploy and test a FunC contract to verify a sample ZK proof
-
+## 🦄 This tutorial will cover
+1. The basics of zero-knowledge cryptography and specifically zk-SNARKs (Zero-Knowledge Succinct Non-Interactive Argument of Knowledge)
+2. Initiating a trusted setup ceremony (using the Powers of Tau)
+3. Writing and compiling a simple ZK circuit (using the Circom language)
+4. Generating, deploying, and testing a FunC contract to verify a sample ZK-proof
-## 🟥🟦 Prove that you can see colors!
-Before we dig into the details of ZK, let's start with a simple problem. Suppose you want to prove to a color-blind person that you can see colors. We can have an interactive solution for this problem.
-Assume the color-blind person (the verifier) finds two identical pieces of paper one is 🟥 and one is 🟦.
+## 🟥🟦 Explaining ZK-proofs with a color-focused example
-The verifier shows one of the pieces of paper to you (the prover) and asks you to remember this color. Then the verifier will bring the paper behind himself and either change the paper or keep it the same and ask you to tell him if the color has changed or not. If you can tell the difference, then you can see colors(or you were just lucky, 50% chance of saying right answer).
+Before we dig into the details of zero-knowledge, let's start with a simple problem. Suppose you want to prove to a color-blind person that it is possible to distinguish between different colors. We’ll use an interactive solution to solve this problem. Assume the color-blind person (the verifier) finds two identical pieces of paper, with one being red 🟥 and one being blue 🟦.
-Now if the verifier do this 10 times, and you can tell the difference every time, then the verifier will be convinced ~99.90234% (1 - (1/2)^10) that you can see colors.
-And if the verifier do this 30 times, then the verifier will be 99.99999990686774% (1 - (1/2)^30) convinced that you can see colors.
+The verifier shows one of the pieces of paper to you (the prover) and asks you to remember the color. Then the verifier holds that specific piece of paper behind their back and either keeps it the same or changes it and asks you whether the color has changed or not. If you can tell the difference, then you can see colors (or you were just lucky because you had a 50% chance of guessing the correct color).
-But this is an interactive solution, and we can't have a DApp that ask user to send 30 transactions to prove some claim! So we need a non-interactive solution. And this is where Zk-SNARKs and STARKs come in.
+Now if the verifier completes this process 10 times, and you can tell the difference each time, then the verifier is ~99.90234% (1 - (1/2)^10) confident that the correct colors are being used. Therefore, if the verifier completes the process 30 times, then the verifier will be 99.99999990686774% (1 - (1/2)^30) confident.
-We will only cover Zk-SNARK in this tutorial, but you can read more about STARKs [here](https://starkware.co/stark/) and the comparison between Zk-SNARK and STARK [here](https://blog.pantherprotocol.io/zk-snarks-vs-zk-starks-differences-in-zero-knowledge-technologies/).
+Nonetheless, this is an interactive solution and it's not efficient to have a DApp that asks users to send 30 transactions to prove specific data. Therefore, a non-interactive solution is needed; this is where Zk-SNARKs and Zk-STARKs come in.
-### 🎯 Zk-SNARK: Zero-knowledge Succinct Non-Interactive ARgument of Knowledge
+For the purposes of this tutorial, we’ll only cover Zk-SNARKs. However, you can read more about how Zk-STARKs work on the [StarkWare website](https://starkware.co/stark/), while info that compares the differences between Zk-SNARKs and Zk-STARKs can be found on this [Panther Protocol blog post](https://blog.pantherprotocol.io/zk-snarks-vs-zk-starks-differences-in-zero-knowledge-technologies/).**
-Zk-SNARK is a non-interactive proof system where the prover can prove to the verifier that a statement is true by just submitting one proof. And the verifier can verify the proof in a very short time.
+### 🎯 Zk-SNARK: Zero-Knowledge Succinct Non-Interactive Argument of Knowledge
-Zk-SNARK consists of three phases:
-* Conducting trusted setup by [MPC](https://en.wikipedia.org/wiki/Secure_multi-party_computation) protocol to generate proving and verification keys (Powers of TAU)
-* generating proof by prover using prover key, public input, and secret input (witness)
-* and verifying the proof
+A Zk-SNARK is a non-interactive proof system where the prover can demonstrate to the verifier that a statement is true by simply submitting one proof. And the verifier is able to verify the proof in a very short time. Typically, dealing with a Zk-SNARK consists of three main phases:
+* Conducting a trusted setup using a [multi-party computation (MPC)](https://en.wikipedia.org/wiki/Secure_multi-party_computation) protocol to generate proving and verification keys (using Powers of TAU)
+* Generating a proof using a prover key, public input, and secret input (witness)
+* Verifying the proof
Let's set up our development environment and start coding!
-## ⚙ Setup development environment
-Let's start by creating an empty [blueprint](https://github.com/ton-org/blueprint) project
+## ⚙ Development environment setup
-1. Create new project using blueprint and then enter a name for your contract (e.g. ZkSimple) and then choose 1st option (simple contract)
+Let's begin the process by taking the following steps:
+
+1. Create a new project called "simple-zk" using [Blueprint](https://github.com/ton-org/blueprint) by executing the following command, after that, enter a name for your contract (e.g. ZkSimple) and then select the 1st option (using an empty contract).
```bash
npm create ton@latest simple-zk
```
-2. Now we need to clone the [snarkjs repo](https://github.com/kroist/snarkjs) that is adjusted to support FunC contracts
+
+2. Next we’ll clone the [snarkjs repo](https://github.com/kroist/snarkjs) that is adjusted to support FunC contracts
```bash
git clone https://github.com/kroist/snarkjs.git
cd snarkjs
@@ -58,14 +54,13 @@ npm ci
cd ../simple-zk
```
-3. Install required libraries for ZkSNARK
+3. Then we’ll install the required libraries needed for ZkSNARKs
```bash
npm add --save-dev snarkjs ffjavascript
npm i -g circom
```
-
-4. Add this section to package.json(Some of the opcodes that we will use are not available in the mainnet release yet)
+4. Next we’ll add the below section to the package.json (note that some of the opcodes that we’ll use are not available in the mainnet release yet)
```json
"overrides": {
"@ton-community/func-js-bin": "0.4.5-tvmbeta.1",
@@ -73,22 +68,20 @@ npm i -g circom
}
```
-5. Also we need to change the version of `@ton-community/sandbox` to be able to use [latest TVM updates](https://t.me/thetontech/56)
+5. Additionally, we’ll need to change the version of the @ton-community/sandbox to be able to use the [latest TVM updates](https://t.me/thetontech/56)
```bash
npm i --save-dev @ton-community/sandbox@0.12.0-tvmbeta.1
```
-
-
Great! Now we are ready to start writing our first ZK project on TON!
-We currently have two main folders in our project:
-* `simple-zk` folder: contains our blueprint template, and it's where we will write our circuit and contracts and tests(always stay in this folder)
+We currently have two main folders that make up our ZK project:
+* `simple-zk` folder: contains our Blueprint template which will enable us to write our circuit and contracts and tests
* `snarkjs` folder: contains the snarkjs repo that we cloned in step 2
## Circom circuit
-Firstly let's create a file in `simple-zk/circuits` folder called `test.circom`, and add this code to it:
+First let's create a folder `simple-zk/circuits` and then create a file in it and add the following code to it:
```circom
template Multiplier() {
signal private input a;
@@ -103,19 +96,19 @@ template Multiplier() {
component main = Multiplier();
```
-This is a simple multiplier circuit. Using this circuit we can prove that we know two numbers that when multiplied together, the result is a specific number(c). Without revealing the numbers(a and b) themselves.
+Above we added a simple multiplier circuit. By using this circuit we can prove that we know two numbers that when multiplied together result in a specific number (c) without revealing the corresponding numbers (a and b) themselves.
-You can read more about circom language [here](https://docs.circom.io/).
+To read more about the circom language consider having a look at [this website](https://docs.circom.io/).
-Then let's make a folder for our build files and move there:
+Next we’ll create a folder for our build files and move the data there by conducting the following (while being in the `simple-zk` folder):
```bash
mkdir -p ./build/circuits
cd ./build/circuits
```
-### 💪 Trusted setup (Powers of TAU)
-It's time to perform a trusted setup. For this, we will use [Powers of Tau](https://a16zcrypto.com/posts/article/on-chain-trusted-setup-ceremony/) method
-(it will probably take a few minutes to finish):
+### 💪 Creating a trusted setup with Powers of TAU
+
+Now it's time to build a trusted setup. To carry out this process, we’ll make use of the [Powers of Tau](https://a16zcrypto.com/posts/article/on-chain-trusted-setup-ceremony/) method (which probably takes a few minutes to complete). Let’s get into it:
```bash
echo 'prepare phase1'
node ../../../snarkjs/build/cli.cjs powersoftau new bls12-381 14 pot14_0000.ptau -v
@@ -131,38 +124,36 @@ echo 'Verify the final ptau'
node ../../../snarkjs/build/cli.cjs powersoftau verify pot14_final.ptau
```
-This will create `pot14_final.ptau` file in the `build/circuits` folder which we can use for any circuits that we will write any future.
-
+After the process above is completed, it will create the pot14_final.ptau file in the build/circuits folder, which can be used for writing future related circuits.
:::caution Constraint size
-If you write a more complex circuit with more constraints you'll have to generate your PTAU setup with bigger parameter.
+If a more complex circuit is written with more constraints, it is necessary to generate your PTAU setup using a larger parameter.
:::
-
You can remove the unnecessary files:
```bash
rm pot14_0000.ptau pot14_0001.ptau pot14_0002.ptau pot14_beacon.ptau
```
-### 📜 Compile circuit
+### 📜 Circuit compilation
-Now let's compile the circuit(be sure to run this command from `build/circuits` folder)
+Now let's compile the circuit by running the following command from the `build/circuits` folder:
```bash
circom ../../circuits/test.circom --r1cs circuit.r1cs --wasm circuit.wasm --prime bls12381 --sym circuit.sym
```
-Now we have our circuit compiled to `build/circuits/circuit.sym`, `build/circuits/circuit.r1cs` and `build/circuits/circuit.wasm` files.
+Now we have our circuit compiled to the `build/circuits/circuit.sym`, `build/circuits/circuit.r1cs`, and `build/circuits/circuit.wasm` files.
:::info altbn-128 and bls12-381 curves
-These are the curves that are currently supported by snarkjs. On Ethereum, the [altbn-128](https://eips.ethereum.org/EIPS/eip-197) curve is only supported, but on TON only bls12-381 curve is supported.
+The altbn-128 and bls12-381 elliptic curves are currently supported by snarkjs. The [altbn-128](https://eips.ethereum.org/EIPS/eip-197) curve is only supported on Ethereum. However, on TON only the bls12-381 curve is supported.
:::
-Let's check the constraint size of our circuit:
+Let's check the constraint size of our circuit by entering the following command:
```bash
node ../../../snarkjs/build/cli.cjs r1cs info circuit.r1cs
```
-As a result, we should get:
+Therefore, the correct result should be:
```bash
[INFO] snarkJS: Curve: bls12-381
[INFO] snarkJS: # of Wires: 4
@@ -173,38 +164,38 @@ As a result, we should get:
[INFO] snarkJS: # of Outputs: 1
```
-Now we can generate the reference zkey
+Now we can generate the reference zkey by executing the following:
```bash
node ../../../snarkjs/build/cli.cjs zkey new circuit.r1cs pot14_final.ptau circuit_0000.zkey
```
-Let's add a contribution to the zkey
+Then we’ll add the below contribution to the zkey:
```bash
echo "some random text" | node ../../../snarkjs/build/cli.cjs zkey contribute circuit_0000.zkey circuit_0001.zkey --name="1st Contributor Name" -v
```
-Let's export the final zkey
+Next, let's export the final zkey:
```bash
echo "another random text" | node ../../../snarkjs/build/cli.cjs zkey contribute circuit_0001.zkey circuit_final.zkey
```
-Now we have our final zkey in `build/circuits/circuit_final.zkey` file. We can verify it:
+Now we have our final zkey present in the `build/circuits/circuit_final.zkey` file. The zkey is then verified by entering the following:
```bash
node ../../../snarkjs/build/cli.cjs zkey verify circuit.r1cs pot14_final.ptau circuit_final.zkey
```
-It's time to generate the verification key
+Finally, it's time to generate the verification key:
```bash
node ../../../snarkjs/build/cli.cjs zkey export verificationkey circuit_final.zkey verification_key.json
```
-You can remove the unnecessary files:
+Then we’ll remove the unnecessary files:
```bash
rm circuit_0000.zkey circuit_0001.zkey
```
-`build/circuits` folder should look like this:
+After conducting the above processes, the `build/circuits` folder should be displayed as follows:
```
build
└── circuits
@@ -216,18 +207,18 @@ build
└── verification_key.json
```
-### ✅ Export Verifier Contract
-Final step in this section is to generate the FunC verifier contract which we will use in our project.
+
+### ✅ Exporting the verifier contract
+
+The final step in this section is to generate the FunC verifier contract which we’ll use in our ZK project.
```bash
node ../../../snarkjs/build/cli.cjs zkey export funcverifier circuit_final.zkey ../../contracts/verifier.fc
```
+Then the `verifier.fc` file is generated in the `contracts` folder.
-`verifier.fc` file will be generated in `contracts` folder.
-
+## 🚢 Verifier contract deployment
-## 🚢 Deploying Verifier Contract
-
-Take a look at `contracts/verifier.fc` file. It contains the magic of ZK-SNARKs. Let's review it line by line.
+Let's review the `contracts/verifier.fc` file step-by-step because it contains the magic of ZK-SNARKs:
```func
const slice IC0 = "b514a6870a13f33f07bc314cdad5d426c61c50b453316c241852089aada4a73a658d36124c4df0088f2cd8838731b971"s;
@@ -239,7 +230,7 @@ const slice vk_alpha_1 = "a3fa7b5f78f70fbd1874ffc2104f55e658211db8a938445b4a07bd
const slice vk_beta_2 = "b17e1924160eff0f027c872bc13ad3b60b2f5076585c8bce3e5ea86e3e46e9507f40c4600401bf5e88c7d6cceb05e8800712029d2eff22cbf071a5eadf166f266df75ad032648e8e421550f9e9b6c497b890a1609a349fbef9e61802fa7d9af5"s;
```
-These are the constants that verifier contract needs to use in proof verifying. These parameters can be found in `build/circuits/verification_key.json` file.
+Above are the constants that verifier contracts must make use of to implement proof verification. These parameters can be found in the `build/circuits/verification_key.json` file.
```func
slice bls_g1_add(slice x, slice y) asm "BLS_G1_ADD";
@@ -250,9 +241,10 @@ slice bls_g1_multiexp(
) asm "BLS_G1_MULTIEXP";
int bls_pairing(slice x1, slice y1, slice x2, slice y2, slice x3, slice y3, slice x4, slice y4, int n) asm "BLS_PAIRING";
```
-These lines are the new [TVM Opcodes](https://docs.ton.org/learn/tvm-instructions/tvm-upgrade-2023-07#bls12-381)(BLS12-381) that make the pairing check feasible on the TON blockchain.
+The above lines are the new [TVM opcodes](https://docs.ton.org/learn/tvm-instructions/tvm-upgrade-2023-07#bls12-381) (BLS12-381) that allow pairing checks to be conducted on the TON Blockchain.
+
+The load_data and save_data functions are simply used to load and save the proof verification results (only for test purposes).
-The `load_data` and `save_data` functions which is here just used to load and save the result of proof check(only for test purposes).
```func
() load_data() impure {
@@ -272,9 +264,7 @@ The `load_data` and `save_data` functions which is here just used to load and sa
}
```
-
-Then there are some simple util functions that is used to load the proof data sent to the contract.
-
+Next there are several simple util functions that are used to load the proof data sent to the contract:
```func
(slice, slice) load_p1(slice body) impure {
...
@@ -289,7 +279,7 @@ Then there are some simple util functions that is used to load the proof data se
}
```
-And the last part is the `groth16Verify` function which check the proof sent to the contract.
+And the last part is the groth16Verify function which is required to check the validity of the proof sent to the contract.
```func
() groth16Verify(
slice pi_a,
@@ -326,7 +316,7 @@ And the last part is the `groth16Verify` function which check the proof sent to
}
```
-Now we need to edit the two files in `wrappers` folder. First is `ZkSimple.compile.ts` file(if you set another name in the step 1, this name is different). We need to put the `verifier.fc` file in the list of contracts to compile.
+Now it’s necessary to edit the two files in the `wrappers` folder. The first file that needs our attention is the `ZkSimple.compile.ts` file (if another name for the contract was set in step 1, its name will be different). We’ll put the `verifier.fc` file in the list of contracts that must be compiled.
```ts
import { CompilerConfig } from '@ton-community/blueprint';
@@ -337,14 +327,15 @@ export const compile: CompilerConfig = {
};
```
-And the other file is `ZkSimple.ts`. We need to first add the opcode of `verify` to the `Opcodes` enum:
+The other file that needs attention is `ZkSimple.ts`. We need to first add the opcode of `verify` to the `Opcodes` enum:
+
```ts
export const Opcodes = {
verify: 0x3b3cca17,
};
```
-And then we need to add the `sendVerify` function to the `ZkSimple` class. This function will be used to send the proof to the contract and test it. The function is like this:
+Next, it’s necessary to add the `sendVerify` function to the `ZkSimple` class. This function is used to send the proof to the contract and test it and is presented as follows:
```ts
async sendVerify(
provider: ContractProvider,
@@ -384,7 +375,7 @@ async sendVerify(
}
```
-We also need to add `cellFromInputList` function to the `ZkSimple` class. This function will be used to create a cell from the public inputs which will be sent to the contract.
+Next, we’ll add the `cellFromInputList` function to the `ZkSimple` class. This function is used to create a cell from the public inputs which will be sent to the contract.
```ts
cellFromInputList(list: bigint[]) : Cell {
var builder = beginCell();
@@ -398,7 +389,7 @@ We also need to add `cellFromInputList` function to the `ZkSimple` class. This f
}
```
-And the last function to add to the `ZkSimple` class is `getRes` function. This function will be used to get the result of the proof check.
+Finally, the last function we’ll add to the `ZkSimple` class is the `getRes` function. This function is used to receive the proof verification result.
```ts
async getRes(provider: ContractProvider) {
const result = await provider.get('get_res', []);
@@ -406,14 +397,14 @@ And the last function to add to the `ZkSimple` class is `getRes` function. This
}
```
-Now we can run the tests to deploy the contract. It should pass the deployment test(run this command in the root of `simple-zk` folder)
+Now we can run the required tests needed to deploy the contract. For this to be possible, the contract should be able to successfully pass the deployment test. Run this command in the root of `simple-zk` folder:
```bash
npx blueprint test
```
-
## 🧑💻 Writing tests for the verifier
-Let's open the `ZkSimple.spec.ts` file in the `tests` folder and write a test for the `verify` function. The test will be like this:
+
+Let's open the `ZkSimple.spec.ts` file in the `tests` folder and write a test for the `verify` function. The test is conducted as follows:
```ts
describe('ZkSimple', () => {
let code: Cell;
@@ -440,23 +431,22 @@ describe('ZkSimple', () => {
});
```
-Firstly, we need to import some packages that we will use in the test:
+First, we’ll need to import several packages that we will use in the test:
```ts
import * as snarkjs from "snarkjs";
import path from "path";
import {buildBls12381, utils} from "ffjavascript";
const {unstringifyBigInts} = utils;
````
-* if you run the test, you will get a typescript error, because we don't have declaration file for module 'snarkjs' & ffjavascript. We can fix this by editing the
-`tsconfig.json` file in the root of `simple-zk` folder. We need to change the _**strict**_ option to **_false_**.
-
-We will also need to import `circuit.wasm` and `circuit_final.zkey` files. We will use them to generate the proof to send to the contract.
+* If you run the test, the result will be a TypeScript error, because we don't have a declaration file for the module 'snarkjs' & ffjavascript. This can be addressed by editing the `tsconfig.json` file in the root of the `simple-zk` folder. We'll need to change the _**strict**_ option to **_false_** in that file
+*
+We'll also need to import the `circuit.wasm` and `circuit_final.zkey` files which will be used to generate the proof to send to the contract.
```ts
const wasmPath = path.join(__dirname, "../build/circuits", "circuit.wasm");
const zkeyPath = path.join(__dirname, "../build/circuits", "circuit_final.zkey");
```
-Lets fill the `should verify` test. We will need to generate the proof first.
+Let's fill the `should verify` test. We'll need to generate the proof first.
```ts
it('should verify', async () => {
// proof generation
@@ -478,7 +468,8 @@ it('should verify', async () => {
});
```
-We need to define `g1Compressed`, `g2Compressed`, and `toHexString` functions. They will be used to convert the proof to the format that the contract expects.
+To carry out the next step it is necessary to define the `g1Compressed`, `g2Compressed`, and `toHexString` functions. They will be used to convert the cryptographic proof to the format that the contract expects.
+
```ts
function g1Compressed(curve, p1Raw) {
let p1 = curve.G1.fromObject(p1Raw);
@@ -513,7 +504,7 @@ function toHexString(byteArray) {
}
```
-Now we can send the proof to the contract. We will use the `sendVerify` function for this. The `sendVerify` function expects 5 parameters: `pi_a`, `pi_b`, `pi_c`, `pubInputs` and `value`.
+Now we can send the cryptographic proof to the contract. We'll use the sendVerify function for this. The `sendVerify` function expects 5 parameters: `pi_a`, `pi_b`, `pi_c`, `pubInputs`, and `value`.
```ts
it('should verify', async () => {
// proof generation
@@ -543,12 +534,12 @@ it('should verify', async () => {
});
```
-Are you ready to verify your first proof on TON blockchain? let's run the test and see the result:
+Are you ready to verify your first proof on TON blockchain? To start off this process, let's run the Blueprint test by inputting the following:
```bash
npx blueprint test
```
-Result should be like this:
+The result should be as follows:
```bash
PASS tests/ZkSimple.spec.ts
ZkSimple
@@ -562,23 +553,27 @@ Time: 4.335 s, estimated 5 s
Ran all test suites.
```
-You can check the repo that contains the code of this tutorial [here](https://github.com/SaberDoTcodeR/zk-ton-doc).
+In order to check the repo that contains the code from this tutorial, click on the following link found [here](https://github.com/SaberDoTcodeR/zk-ton-doc).
+
## 🏁 Conclusion
-In this tutorial
-* you learned about ZK and specifically ZkSnark.
-* Then you write your first Circom circuit and compiled it.
-* You also performed MPC and a Powers of TAU ceremony Which you used to generate verification keys for your circuit.
-* Then you used Snarkjs library to export a FunC verifier of your circuit.
-* You used blueprint to deploy and write tests for your verifier.
+In this tutorial you learned the following skills:
+
+* The intricacies of zero-knowledge and specifically ZK-SNARKs
+* Writing and compiling Circom circuiting
+* Increased familiarity with MPC and the Powers of TAU, which were used to generate verification keys for a circuit
+* Became familiar with a Snarkjs library to export a FunC verifier for a circuit
+* Became familiar with Blueprint for verifier deployment and test writing
+
+Note: The above examples taught us how to build a simple ZK use case. That said, there are a wide range of highly complex ZK-focused use cases that can be implemented in a wide range of industries. Some of these include:
+
+* private voting systems 🗳
+* private lottery systems 🎰
+* private auction systems 🤝
+* private transactions💸 (for Toncoin or Jettons)
-This was just a simple ZK use case and there are many more complex use-cases that you can be implemented using ZK.
-* private voting system🗳
-* private lottery system🎰
-* private auction system🤝
-* private transactions💸(TON or JETTON)
+If you have any questions or encounter any errors in this tutorial, feel free to write to the author: [@saber_coder](https://t.me/saber_coder)
-If you have any questions or have noticed an error - feel free to write to the author - [@saber_coder](https://t.me/saber_coder)
## 📌 References
@@ -597,4 +592,4 @@ If you have any questions or have noticed an error - feel free to write to the a
## 📬 About the author
-- Saber on [Telegram](https://t.me/saber_coder) or [Github](https://github.com/saberdotcoder) or [LinkedIn](https://www.linkedin.com/in/szafarpoor/)
+- Saber on [Telegram](https://t.me/saber_coder) or [GitHub](https://github.com/saberdotcoder) or [LinkedIn](https://www.linkedin.com/in/szafarpoor/)
diff --git a/docs/develop/data-formats/cell-boc.mdx b/docs/develop/data-formats/cell-boc.mdx
index 1544623d3e..e5d4085235 100644
--- a/docs/develop/data-formats/cell-boc.mdx
+++ b/docs/develop/data-formats/cell-boc.mdx
@@ -4,6 +4,7 @@ import ThemedImage from '@theme/ThemedImage';
## Cell
A cell represents a data structure on TON Blockchain. Cells are able to store up to 1023 bits and possess up to 4 references to other cells.
+````mdx-code-block
-
+````
## Bag of Cells
Bag of Cells (BoC) is a format for serializing cells into byte arrays, which is further described in the [TL-B schema](https://github.com/ton-blockchain/ton/blob/24dc184a2ea67f9c47042b4104bbb4d82289fac1/crypto/tl/boc.tlb#L25).
+````mdx-code-block
-
+````
On TON, everything consists of cells, including contract code, stored data, blocks, achieving streamline and robust flexibility in the process.
+````mdx-code-block
-
+````
### Cell serialization
Let's analyze our first example of a Bag of Cells :
+````mdx-code-block
-
+````
```json
1[8_] -> {
24[0AAAAA],
@@ -112,7 +116,7 @@ Now let's add the refs indexes:
And put it all together:
```json
0201 C0 0201
-0101 AA 02
+0101 FF 02
0006 0AAAAA
```
@@ -125,17 +129,17 @@ And concat it by joining the corresponding strings into a single array of bytes:
```golang
func (c *Cell) descriptors() []byte {
-ceilBytes := c.bitsSz / 8
-if c.bitsSz%8 ! = 0 {
-ceilBytes++
-}
+ ceilBytes := c.bitsSz / 8
+ if c.bitsSz%8 ! = 0 {
+ ceilBytes++
+ }
// calc size
- ln := ceilBytes + c.bitsSz/8
+ ln := ceilBytes + c.bitsSz / 8
specBit := byte(0)
if c.special {
- specBit = 8
+ specBit = 8
}
return []byte{byte(len(c.refs)) + specBit + c.level*32, byte(ln)}
diff --git a/docs/develop/data-formats/crc32.md b/docs/develop/data-formats/crc32.md
index b290ba9f0f..1988b160a3 100644
--- a/docs/develop/data-formats/crc32.md
+++ b/docs/develop/data-formats/crc32.md
@@ -14,6 +14,10 @@ The CRC32 IEEE version used for TL-B schemes. By viewing this [NFT op code](http
* [Online calculator example](https://emn178.github.io/online-tools/crc32.html)
* [Tonwhales Introspection ID Generator](https://tonwhales.com/tools/introspection-id)
+### VS Code extension
+
+* [crc32-opcode-helper](https://marketplace.visualstudio.com/items?itemName=Gusarich.crc32-opcode-helper)
+
### Python
```python
diff --git a/docs/develop/data-formats/library-cells.md b/docs/develop/data-formats/library-cells.md
new file mode 100644
index 0000000000..a9cd18e63c
--- /dev/null
+++ b/docs/develop/data-formats/library-cells.md
@@ -0,0 +1,137 @@
+# Library Cells
+
+## Introduction
+One of the native feature of how TON stores data in Cells is deduplication: in storage, messages, blocks, transactions and so on duplicate cells are stored only once. This tremendously decrease size of serialized data, and allows efficient storage of step-wise updated data.
+
+For the same reason many structures in TON are simultaneously rich, convinient and efficient: block structure contains the same copy of each message in many places: in Message queue, in list of Transaction, in Merkle updates and so on: since duplication has no overhead we can store data multiple times where we need it without worring about efficiency.
+
+Library cells employ a deduplication mechanism on-chain, allowing the integration of this technology into custom smart contracts.
+:::info
+If you store jetton-wallet code as library cell (1 cell and 256+8 bits, instead of ~20 cells and 6000 bits) for instance, forward fees for a message that contains `init_code` will be decreased from 0.011 to 0.003 TON.
+:::
+
+## General Info
+
+Lets consider basechain step from block 1'000'000 to block 1'000'001. While each block contains small amount of data (usually less than 1000 transactions), the whole Basechain state contains millions of accounts and since blockchain need to keep integrity of the data (in particular to commit merkle root hash of whole state to the block) whole tree of the state need to be updated.
+
+For the blockchains of previous generations this means that generally you keep track of only recent states because storing separate chain states for each block will require too much space. But in TON Blockchain due to deduplication, for each block you only add to storage new cells. This not only make processing faster but also allows you to efficiently work with history: check balances, states and even run getmethods for any point in history without much overhead!
+
+For the case when we have a family of similar contracts (for instance jetton-wallets), node stores duplicating data (the same code of each jetton-wallet) only once. Library Cells allows to utilize deduplication mechanism for such contracts to decrease storage and forward fees.
+
+:::info Highlevel analogy
+You can consider library cell as C++ pointer: one small cell that points to larger Cell with (possibly) many refs. The referenced cell (cell to which library cell points) should exist and registered in public context (_"published"_).
+:::
+
+## Structure of Library Cells
+
+Library cell is [exotic cell](/develop/data-formats/exotic-cells) that contains a reference to some other static cell. In particular it contains 256 bit of hash of referenced cell.
+
+For TVM, library cells works as follows: whenever TVM receives a command to open a cell to a slice (TVM Instruction: `CTOS`, funC method: `.begin_parse()`), it searches cell with the corresponding hash from library cell in the Masterchain library context. If found it, it opens referenced cell and returns its slice.
+
+Opening library cell costs the same as opening ordinar cell, so it can be used as transparent replacement for static cells that however occupy much less space (and thus costs less fees for storage and sending).
+
+Note that it is possible to create a library cell that references another library cell, which in turn references another, and so on. For such case `.begin_parse()` will raise exception. Such library however can be unwrapped step-wise with `XLOAD` opcode.
+
+Another important peculiarities of Library Cell is that since it contains hash of referenced cell it is ultimatively reference to some satic data. You can not change data to which this library cell is referenced.
+
+To be found in the Masterchain library context and thus referenced by a Library Cell, a source Cell needs to be published in the Masterchain. This means that a smart contract existing in the Masterchain needs to add this cell to its state with the `public=true` flag. This can be accomplished using the `SETLIBCODE` opcode.
+
+## Using in Smart Contracts
+
+Since library cell behaves the same way as ordinary cell it referenced to in all contexts except fee calculation you can just use it instead of any cell with static data. For instance, you can store jetton-wallet code as library cell (so 1 cell and 256+8 bits, instead of usually ~20 cells and 6000 bits) which will result is order magnitude less storage and forward fees. In particular, forward fees for `internal_transfer` message that contains `init_code` will be decreased from 0.011 to 0.003 TON.
+
+### Store Data in the Library Cell
+Lets consider example of storing jetton-wallet code as library cell to decrease fees. First we need to compile jetton-wallet to ordinary cell that contains it's code.
+
+Than you need to create library cell with reference to ordinary cell. Library cell contains 8-bit tag of library `0x02` followed by 256-bit of referenced cell hash.
+
+### Using in Fift
+Basically you need to put tag and hash to the builder and then "close builder as exotic cell".
+
+It can be done in Fift-asm construction like [this](https://github.com/ton-blockchain/multisig-contract-v2/blob/master/contracts/auto/order_code.func), example of compilation some contract directly to library cell [here](https://github.com/ton-blockchain/multisig-contract-v2/blob/master/wrappers/Order.compile.ts).
+
+```fift
+;; https://docs.ton.org/tvm.pdf, page 30
+;; Library reference cell — Always has level 0, and contains 8+256 data bits, including its 8-bit type integer 2
+;; and the representation hash Hash(c) of the library cell being referred to. When loaded, a library
+;; reference cell may be transparently replaced by the cell it refers to, if found in the current library context.
+
+cell order_code() asm "spec PUSHREF";
+```
+### Using in @ton/ton
+Alternatively, you can form Library Cell entirely on ts-level in Blueprint with the `@ton/ton` library:
+
+```ts
+import { Cell, beginCell } from '@ton/core';
+
+let lib_prep = beginCell().storeUint(2,8).storeBuffer(jwallet_code_raw.hash()).endCell();
+jwallet_code = new Cell({ exotic:true, bits: lib_prep.bits, refs:lib_prep.refs});
+```
+
+* Learn source [here](https://github.com/ton-blockchain/stablecoin-contract/blob/de08b905214eb253d27009db6a124fd1feadbf72/sandbox_tests/JettonWallet.spec.ts#L104C1-L105C90).
+
+### Publish ordinary cell in masterchain library context
+Practical example is available [here](https://github.com/ton-blockchain/multisig-contract-v2/blob/master/contracts/helper/librarian.func). The core of this contract is `set_lib_code(lib_to_publish, 2);` - it accepts as input ordinary cell that need to be published and flag=2 (means that everybody can use it).
+
+Note, that contract that publish cell pays for it's storage and storage in masterchain 1000x higher than in basechain. So library cell usage is only efficient for contracts used by thousands users.
+
+### Testing in the Blueprint
+
+To test how contract that use Library Cells work in blueprint you need to manually add referenced cells to library context of blueprint emulator. It can be done this way:
+1) you need to create library context dictionary (Hashmap) `uint256->Cell` where `uint256` is hash of the corresponding Cell.
+2) install library context to the emulator settings.
+
+Example how it can be done is shown [here](https://github.com/ton-blockchain/stablecoin-contract/blob/de08b905214eb253d27009db6a124fd1feadbf72/sandbox_tests/JettonWallet.spec.ts#L100C9-L103C32).
+
+:::info
+Note, that current blueprint version (`@ton/blueprint:0.19.0`) doesn't automatically update library context if some contract during emulation publish new library, you need do it manually.
+Actual for 04.2024 and suppose to be enhanced in the near future.
+:::
+
+### Get Methods for Library Cell Based Contracts
+
+You have jetton-wallet with its code stored in a library cell and desire to check balance.
+
+To check its balance, you need to execute a get method in the code. This involves:
+- accessing the library cell
+- retrieving the hash of the referenced cell
+- finding the cell with that hash in the masterchain's library collection
+- executing the code from there.
+
+In Layered Solutions (LS), all these processes happen behind the scenes without the user needing to know about the specific code storage method.
+
+However, when working locally, things are different. For example, if you use an explorer or wallet, you may take an account state and try to determine its type—whether it's an NFT, wallet, token, or auction.
+
+For regular contracts, you can look at the available get methods, i.e., the interface, to understand it. Or, you may "steal" an account state to my local pseudonet and execute methods there.
+
+For the a library cell, this isn't possible because it doesn't contain data on its own. You must manually detect and retrieve the necessary cells from the context. This can be done through LS (though bindings do not yet support this) or via DTon.
+
+
+#### Retrieving Library Cell with Liteserver
+Liteserver when running get methods automatically set correct library context. If you want to detect type of contract by get methods or run getmethods locally you need to download corresponding cells via LS method [liteServer.getLibraries](https://github.com/ton-blockchain/ton/blob/4cfe1d1a96acf956e28e2bbc696a143489e23631/tl/generate/scheme/lite_api.tl#L96).
+
+#### Retrieving Library Cell with DTon
+You can also get library from [dton.io/graphql](https://dton.io/graphql):
+```
+{
+ get_lib(
+ lib_hash: ""
+ )
+}
+```
+as well as list of libraries for specific masterchain block:
+```
+{
+ blocks{
+ libs_publishers
+ libs_hash
+ }
+}
+```
+
+## See Also
+
+* [Exotic Cells](/develop/data-formats/exotic-cells)
+* [TVM Instructions](/learn/tvm-instructions/instructions)
+
+
diff --git a/docs/develop/data-formats/msg-tlb.mdx b/docs/develop/data-formats/msg-tlb.mdx
index f516ea72ae..7ed1e060b1 100644
--- a/docs/develop/data-formats/msg-tlb.mdx
+++ b/docs/develop/data-formats/msg-tlb.mdx
@@ -67,6 +67,7 @@ Recall how `Maybe` and `Either` works, we can serialize different cases:
* `[CommonMsgInfo][10][StateInit][0][X]` - `Message X` in the one cell
+````mdx-code-block
-
+````
* `[CommonMsgInfo][11][^StateInit][1][^X]` - `Message X` with references
+````mdx-code-block
-
+````
@@ -148,7 +150,7 @@ int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool
### ext_in_msg_info$10
-`ext_in_msg_info$10` is a case of external incoming message. This means this type of messages sent from contracts to off-chain space.\
+`ext_in_msg_info$10` is a case of external incoming message. This means this type of messages sent from contracts to off-chain space.
Use case - wallet application request to wallet contract.
diff --git a/docs/develop/data-formats/proofs.mdx b/docs/develop/data-formats/proofs.mdx
index 7fa38dc2a2..f8873856c9 100644
--- a/docs/develop/data-formats/proofs.mdx
+++ b/docs/develop/data-formats/proofs.mdx
@@ -98,7 +98,7 @@ assert h_proof.refs[0].get_hash(0) == block_id.root_hash
```
Now, we can trust all other data, this Cell contains
-_Checking Proof Examples:_ [Python](https://github.com/yungwine/pytoniq/blob/master/pytoniq/proof/check_proof.py#L33), [Kotlin](https://github.com/andreypfau/ton-kotlin/blob/b1edc4b134e89ccf252149f27c85fd530377cebe/ton-kotlin-liteclient/src/commonMain/kotlin/CheckProofUtils.kt#L15), [C++](https://github.com/ton-blockchain/ton/blob/24dc184a2ea67f9c47042b4104bbb4d82289fac1/crypto/block/check-proof.cpp#L34)
+_Checking Proof Examples:_ [Python](https://github.com/yungwine/pytoniq-core/blob/873a96aa2256db33b8f35fbe2ab8fe8cf8ae49c7/pytoniq_core/proof/check_proof.py#L19), [Kotlin](https://github.com/andreypfau/ton-kotlin/blob/b1edc4b134e89ccf252149f27c85fd530377cebe/ton-kotlin-liteclient/src/commonMain/kotlin/CheckProofUtils.kt#L15), [C++](https://github.com/ton-blockchain/ton/blob/24dc184a2ea67f9c47042b4104bbb4d82289fac1/crypto/block/check-proof.cpp#L34)
## Full Block
diff --git a/docs/develop/data-formats/tl-b-language.mdx b/docs/develop/data-formats/tl-b-language.mdx
index 3777663ad4..f478c37d3c 100644
--- a/docs/develop/data-formats/tl-b-language.mdx
+++ b/docs/develop/data-formats/tl-b-language.mdx
@@ -13,6 +13,7 @@ We refer to any set of TL-B constructs as TL-B documents. A TL-B document usuall
i.e. their constructors) and functional combinators. The declaration of each combinator ends with a semicolon (`;`).
Here is an example of a possible combinator declaration:
+````mdx-code-block
-
+````
## Constructors
The left-hand side of each equation describes the way to define, or serialize, a value of the type indicated on the
right-hand side. Such a description begins with the name of a constructor.
+````mdx-code-block
-
+````
Constructors are used to specify the type of combinator, including the state at serialization. For example, constructors
can also be used when you want to specify an `op`(operation code) in query to a smart contract in TON.
@@ -107,7 +109,7 @@ tag_a$10 val:(## 32) = A;
tag_b$00 val(## 64) = A;
```
-If we parse `1000000000000000000000000000000001` (1 and 33 zeroes and 1) in TLB type `A` - firstly we need to get first
+If we parse `1000000000000000000000000000000001` (1 and 32 zeroes and 1) in TLB type `A` - firstly we need to get first
two bits to define tag. In this example `10` is two first bits and they represent `tag_a`. So now we know that next 32
bits are `val` variable, `1` in our example. Some "parsed" pseudocode variables may look like:
@@ -200,7 +202,7 @@ form `ident:type-expr`, where ident is an identifier with the name of the field
anonymous fields), and type-expr is the field’s type. The type provided here is a type expression, which may include
simple types, parametrized types with suitable parameters or complex expressions.
-In sum ap all fields defined in type must not be greater than Cell (`1023` bits and `4` refs)
+In sum up all fields defined in type must not be greater than Cell (`1023` bits and `4` refs)
### Simple types
@@ -640,12 +642,6 @@ a comment
// This is one line comment
```
-## IDE Support
-
-The [intellij-ton](https://github.com/andreypfau/intellij-ton) plugin supports Fift, FunC and also TL-B.
-The TL-B grammar is described in
-the [TlbParser.bnf](https://github.com/andreypfau/intellij-ton/blob/main/src/main/grammars/TlbParser.bnf) file.
-
## Useful sources
- [A description of an older version of TL](https://core.telegram.org/mtproto/TL)
diff --git a/docs/develop/data-formats/tl-b-types.mdx b/docs/develop/data-formats/tl-b-types.mdx
index 51b6a2f650..c67d336116 100644
--- a/docs/develop/data-formats/tl-b-types.mdx
+++ b/docs/develop/data-formats/tl-b-types.mdx
@@ -7,7 +7,7 @@ So feel free to read about it later.
:::
-In this section, complex and unconventional typed language binary (TL-B) structures are analyzed. To get started, we recommend reading [this documentation](/learn/overviews/tl-b-language) first to become more familiar with the topic.
+In this section, complex and unconventional typed language binary (TL-B) structures are analyzed. To get started, we recommend reading [this documentation](/develop/data-formats/tl-b-language) first to become more familiar with the topic.
@@ -71,6 +71,7 @@ foo$_ u:(Unary 2) = Foo;
According said above, `Foo` will be deserialized into:
+````mdx-code-block
-
+````
```tlb
foo u:(unary_succ x:(unary_succ x:(unnary_zero)))
@@ -358,4 +359,4 @@ The 32 bytes in the middle are the data of the address itself (also calls Accoun
## References
-_Here a [link to the original article](https://github.com/xssnick/ton-deep-doc/blob/master/TL-B.md) by [Oleg Baranov](https://github.com/xssnick)._
\ No newline at end of file
+_Here a [link to the original article](https://github.com/xssnick/ton-deep-doc/blob/master/TL-B.md) by [Oleg Baranov](https://github.com/xssnick)._
diff --git a/docs/develop/data-formats/tlb-ide.md b/docs/develop/data-formats/tlb-ide.md
index 3012bbe12f..611f209704 100644
--- a/docs/develop/data-formats/tlb-ide.md
+++ b/docs/develop/data-formats/tlb-ide.md
@@ -1,18 +1,7 @@
# IDE Support
+The [intellij-ton](https://github.com/andreypfau/intellij-ton) plugin supports the Fift and FunC programming languages
+as well as the typed language binary (TL-B) format.
-### Highlight
-The [intellij-ton](https://github.com/andreypfau/intellij-ton) plugin supports the Fift and FunC programming languages as well as the typed language binary (TL-B) format.
-
-Additionally, the correct TL-B syntax specifications are described in the [TlbParser.bnf](https://github.com/andreypfau/intellij-ton/blob/main/src/main/grammars/TlbParser.bnf) file.
-
-### TL-B Parsers
-
-TL-B parsers help carry out the serialization of basic [TL-B types](/develop/data-formats/tl-b-types). Each of which implements TL-B types as an object, and returns serialized binary data.
-
-| Language | SDK | Social |
-|------------|-------------------------------------------------------------------------------------------------------------|------------------------|
-| Kotlin | [ton-kotlin](https://github.com/andreypfau/ton-kotlin/tree/main/ton-kotlin-tlb) (+ parsing `.tlb` files) | https://t.me/tonkotlin |
-| Go | [tonutils](https://github.com/xssnick/tonutils-go/tree/master/tlb) | https://t.me/tonutils |
-| Go | [tongo](https://github.com/tonkeeper/tongo/tree/master/tlb) (+ parsing `.tlb` files) | https://t.me/tongo_lib |
-| TypeScript | [tlb-parser](https://github.com/ton-community/tlb-parser) | - |
+Additionally, the correct TL-B syntax specifications are described in
+the [TlbParser.bnf](https://github.com/ton-blockchain/intellij-ton/blob/main/src/main/grammar/TlbParser.bnf) file.
diff --git a/docs/develop/data-formats/tlb-tools.md b/docs/develop/data-formats/tlb-tools.md
new file mode 100644
index 0000000000..6a83fba8be
--- /dev/null
+++ b/docs/develop/data-formats/tlb-tools.md
@@ -0,0 +1,20 @@
+# TL-B Tools
+
+## TL-B Parsers
+
+TL-B parsers help carry out the serialization of basic [TL-B types](/develop/data-formats/tl-b-types). Each of which
+implements TL-B types as an object, and returns serialized binary data.
+
+| Language | SDK | Social |
+|------------|----------------------------------------------------------------------------------------------------------|------------------------|
+| Kotlin | [ton-kotlin](https://github.com/andreypfau/ton-kotlin/tree/main/ton-kotlin-tlb) (+ parsing `.tlb` files) | https://t.me/tonkotlin |
+| Go | [tonutils](https://github.com/xssnick/tonutils-go/tree/master/tlb) | https://t.me/tonutils |
+| Go | [tongo](https://github.com/tonkeeper/tongo/tree/master/tlb) (+ parsing `.tlb` files) | https://t.me/tongo_lib |
+| TypeScript | [tlb-parser](https://github.com/ton-community/tlb-parser) | - |
+| Python | [ton-kotlin](https://github.com/disintar/tonpy) (+ parsing `.tlb` files) | https://t.me/dtontech |
+
+## TL-B Generator
+
+[tlb-codegen](https://github.com/ton-community/tlb-codegen) package allows you to generate Typescript code for serializing and deserializing structures according to the TLB scheme provided.
+
+[tonpy](https://github.com/disintar/tonpy) package allows you to generate Python code for serializing and deserializing structures according to the TLB scheme provided.
diff --git a/docs/develop/ethereum-to-ton/blockchain-services.md b/docs/develop/ethereum-to-ton/blockchain-services.md
new file mode 100644
index 0000000000..83b0abccc4
--- /dev/null
+++ b/docs/develop/ethereum-to-ton/blockchain-services.md
@@ -0,0 +1,32 @@
+# Blockchain services
+
+## Domain Name Systems
+
+In Ethereum, users use the Ethereum Name Service (ENS), which is a decentralized naming system built on top of the Ethereum blockchain.
+
+The TON blockchain includes an embedded domain name system known as the TON DNS. It is a decentralized service that allows users to register human-readable domain names for their smart contracts, websites, or any other online content. Such a device facilitates interaction with decentralized applications (dApps) and other resources on the TON blockchain. The DNS system in TON functions similarly to traditional Internet DNS systems, but its decentralized nature eliminates the need for a centralized authority to control and manage domain names, thereby reducing the risks of censorship, fraud, and domain name hijacking.
+
+## WWW
+
+TON WWW is a part of the TON blockchain that allows you to create and interact with decentralized websites directly through the blockchain. Unlike traditional websites, websites on TON are accessible via special URLs ending in `.ton` and support unique hyperlinks of the `ton://` format that allow transactions and other operations directly from the URL.
+
+One of the key features of TON WWW is the ability to directly bind crypto wallets to domain names, which allows users to send cryptocurrency to addresses like alice.place.ton without additional details. This greatly simplifies the process of donations and payments, making it more intuitive and convenient.
+
+## Proxy
+
+TON Proxy is a tool based on the TON protocol that offers a high level of security and anonymity. All data transmitted through TON Proxy is encrypted, thus protecting users' confidential information.
+
+One of the key advantages of TON Proxy is its ability to bypass blockades imposed by ISPs or government agencies. This makes it an essential tool for users who need free access to information on the Internet without restrictions.
+
+In addition, TON Proxy helps to speed up Internet connection speeds. It automatically selects the servers with the lowest load, which improves the quality of connection and the speed of Internet access.
+
+## Decentralised storage
+
+Ethereum is not suitable for storing large amounts of data. Therefore, decentralized storage on Ethereum typically involves using distributed file systems to store and retrieve data in a decentralized and secure manner. One popular approach to decentralized storage on Ethereum is the InterPlanetary File System (IPFS), which is a peer-to-peer file system that allows users to store and retrieve files from a network of distributed nodes.
+
+TON network has its own decentralised storage service, that is used by the TON Blockchain to store archive copies of blocks and status data (snapshots), but also available for storing users’ files or other services running on the platform, with torrent-like access technology. The most popular use case is to store NFT metadata directly on TON storage, not using additional distributed file storage services like IPFS.
+
+## Payment services
+
+TON Payments is a solution for lightning-fast transactions with zero network fees on the TON blockchain. While the TON blockchain is sufficient for most tasks, some applications, such as TON Proxy, TON Storage or a certain decentralized application, require micro-transactions with much higher speed and lower costs. Payment channels, also known as the Lightning network, were created to solve this problem. Payment channels allow two parties to make transactions off-chain by creating a special smart contract on the blockchain with their initial balances. They can then perform as many transactions between them as they want without any speed limits or fees. The network's fees are only charged when the channel is opened and closed. The technology also guarantees proper operation by allowing a party to close the channel on its own if the other party cheats or disappears.
+
diff --git a/docs/develop/ethereum-to-ton/difference-of-blockchains.md b/docs/develop/ethereum-to-ton/difference-of-blockchains.md
new file mode 100644
index 0000000000..1e0fcacd3e
--- /dev/null
+++ b/docs/develop/ethereum-to-ton/difference-of-blockchains.md
@@ -0,0 +1,58 @@
+# The difference of blockchains
+
+In this chapter, we will examine the key differences between the Ethereum blockchain compared to the TON blockchain. The analysis will include an overview of the network architectures, highlight their unique features, and evaluate the advantages and disadvantages of each.
+
+Starting with an overview of the Ethereum and TON ecosystems, we can note that both platforms offer a similar structure of participants and services, including users who hold assets and make transactions, validators who keep the network up and running and secure, and application developers who use the blockchain as the basis for their products and services. Both ecosystems include both custodial and non-custodial services that provide users with different levels of control over their assets.
+
+Additionally, it is worth highlighting that both platforms facilitate the creation of decentralized applications (DApps), offering developers powerful tools and standards for development.
+
+However, despite the similarities in overall structure and features offered, the key technological aspects and network design approaches of Ethereum and TON differ significantly. These differences lay the foundation for a thorough understanding of the unique advantages and limitations of each platform, which is particularly important for developers seeking to maximize the capabilities of each network. In the following subsections, we will explore these differences in more detail, focusing on the network architecture, models, transaction mechanisms, and transaction settlement system to provide developers with the insights they need.
+
+## Blockchains architecture
+
+Ethereum, by inheriting and extending the foundational principles of Bitcoin, has provided developers with the flexibility needed to create complex decentralized applications (DApps). A unique feature of Ethereum is its ability to provide each account with an individualized data store, allowing transactions to not only perform token transfers, but also to change the state of the blockchain by interacting with smart contracts. This ability to synchronously interact between accounts, as we know, offers great promise for application development, but also raises the issue of scalability. Each transaction on the Ethereum network requires nodes to update and maintain the full state of the blockchain, which leads to significant latency and increases the cost of gas as network utilization increases.
+
+In response to these challenges, TON offers an alternative approach aimed at improving scalability and performance. Designed with the ambition to provide developers with maximum flexibility to create a variety of applications, TON uses the concept of shards and masterchain to optimize the block creation process. In each TON shardchain and masterchain, a new block is generated on average every 5 seconds, ensuring fast transaction execution. Unlike Ethereum, where state updates are synchronous, TON implements asynchronous messaging between smart contracts, allowing each transaction to be processed independently and in parallel, significantly speeding up transaction processing on the network. Sections and articles to familiarize yourself with:
+
+* [Shards](/develop/blockchain/shards)
+* [Comparison of Blockchains document](https://ton.org/comparison_of_blockchains.pdf)
+* [Comparison of Blockchains table (much less informative than the document, but more visual)](/learn/overviews/blockchain-comparison)
+
+In conclusion, by comparing the architecture and technological underpinnings of TON and Ethereum, it is clear that TON offers significant advantages. With its innovative approach to asynchronous transaction processing and unique shard and masterchain architecture, TON demonstrates the potential to support millions of transactions per second without compromising security or centralization. This provides the platform with outstanding flexibility and efficiency, making it ideal for a wide range of applications.
+
+## Account-based model (Ethereum) vs Actor model (TON)
+
+In the first subsection, we made a comparison between Ethereum and TON, highlighting their key architectural differences and the main challenges faced by Ethereum. Of particular note are the different approaches to organizing interactions in these blockchains and using models. These differences come from the unique architectural choices of each platform. For developers accustomed to Ethereum, it is important to deeply understand these differences in order to effectively transition to developing on TON. This understanding will allow the architecture to adapt and optimize the interaction of smart contracts in the new environment.
+
+
+So, let's remember how the account-based model works in Ethereum. Ethereum uses this model to track balances. Like a bank account, funds are stored in accounts rather than in individual coins. There are two types of accounts:
+ - Externally-owned accounts (EOAs) - externally managed accounts are controlled by the user using public and private key pairs. The public key allows others to send payments to the account.
+ - Contract accounts - are controlled by smart contract code rather than private keys. Because they do not have a private key, contract accounts cannot initiate transactions on their own.
+
+When an Ethereum user creates a wallet, an external account is added to the global state on all nodes in the decentralized network when the first transaction is invoked or the first funds are received. Deploying a smart contract creates a contract account capable of storing and distributing funds programmatically based on certain conditions. All account types have balances, storage, and can trigger transactions by calling functions in other accounts. This structure provides Ethereum's ability to serve as programmable money.
+
+Ethereum has synchronous transaction processing, where each transaction is processed sequentially, in strict order. This ensures that the state of the blockchain always remains consistent and predictable for all participants in the network. All transactions are atomic, it either fully completes successfully or fully completes unsuccessfully, without any partial or incomplete execution. Moreover, when a smart contract is invoked and it in turn invokes another smart contract, the invocation is instantaneous within the same transaction. But here again there are disadvantages, a transaction can grow as much as it is allowed to grow. A negative effect of synchronicity is still overloading, as computations cannot run in parallel. The number of contracts and users grows and the inability to parallelize computations becomes a major limiting factor in the growth of the network.
+
+Now let's understand what is actor model? Actor model is an approach to parallel and distributed computing where the main element is an actor - an independent executable block of code. Originally developed for cluster computing, this model is widely used in micro-server architectures to meet the needs of modern distributed systems due to its ability to scale, parallelism and fault tolerance. Actors receive and process messages, depending on the logic of the message, respond by accepting local changes or performing actions in response, can create other actors or send messages onward. They are thread-safe and reentrant, eliminating the need for locks and simplifying parallel processing of tasks. This model is ideal for building scalable and reliable server solutions, providing efficient concurrent access control and support for both synchronous and asynchronous messaging.
+
+In TON, everything is represented by smart contracts, which can also be called actor in the context of actor model. A smart contract is an object with properties such as address, code, data and balance. It has the ability to store data and behaves according to instructions received from other smart contracts. After a contract receives a message and processes it by executing its code in the TVM, various scenarios can occur:
+- The contract changes its properties `code, data, balance`
+- The contract optionally generates an outgoing message
+- The contract goes into standby mode until the following event occurs
+
+The result of scripts is always the creation of a transaction. The transactions themselves are asynchronous, meaning that the system can continue processing other transactions while waiting for past transactions to complete. This provides more flexibility when processing complex transactions. Sometimes a single transaction may require multiple smart contract calls to be executed in a specific sequence. Because these calls are asynchronous, developers can more easily design and implement complex transaction flows that may involve multiple concurrent operations. A developer coming from Ethereum needs to realize that smart contracts in the TON blockchain can only communicate with each other by sending asynchronous messages, which means that if there is a need to request data from another contract and an immediate response is required, this will not be possible. Instead `get methods` must be called by clients outside the network, much like a wallet in Ethereum uses RPC nodes such as Infura to request smart contract states. This is an important limitation for several reasons. For example, flash loans are transactions that must be executed within a single block, relying on the ability to borrow and repay in the same transaction. This is facilitated by the synchronous nature of Ethereum's EVM, but in TON, the asynchronous nature of all transactions makes executing a flash loan infeasible. Also Oracles, which provide smart contracts with external data, involve a more intricate design process in TON. What Oracles are and how to use them in TON can be found [here](/develop/oracles/about_blockchain_oracles).
+
+## The difference of wallets
+
+We have already discussed that in Ethereum, a user's wallet is generated based on their address, which is in a 1-to-1 relationship with their public key. But in TON, all wallets are smart contracts that must be deployed by the user himself. Since smart contracts can be configured in different ways and have different features, there are several versions of wallets, which you can read about [here](/participate/wallets/contracts). Due to the fact that wallets are smart contracts, a user can have multiple wallets with different addresses and initial parameters. To send a transaction, the user must sign the message with his private key and send it to his wallet contract, which in turn forwards it to the smart contract of a particular DApp application. This approach greatly increases flexibility in wallet design and developers can add new versions of the wallet in the future. In Ethereum at the moment developers are actively using multi-sig wallets (smart contracts) like gnosis and are just starting to introduce so-called `account-abstractions' like ERC-4337, where wallets will be filled with such functionality as sending transactions without a native token, account recovery, after its loss, etc., but it's worth noting, wallet accounts are much more expensive to use in terms of gas fees compared to EOA in Ethereum.
+
+## Messages and Transactions
+
+What happens between two contracts is called a message - a small number of tokens and arbitrary data are sent to a specified address. When the message arrives at the contract, it is processed by the contract code, the contract updates its state and optionally sends a new message. All these actions on the contract are recorded as transactions. Let's imagine an example, we have a chain of messages, from contract `A` to contract `B`, from contract `B`, to contract `C`, then we will have two messages and three transactions. But initially, to change the state of the blockchain, you need an outside signal. To invoke a smart contract, you need to send an external message that goes to the validators and they apply it to the smart contract. And we already discussed in the last subsection that a wallet is a smart contract, so this external message usually first goes to the wallet's smart contract, which records them as the first transaction and that first transaction usually contains an embedded message for the actual destination contract. When the wallet smart contract receives the message, it processes it and delivers it to the destination contract (in our example, contract `A` could be a wallet and when it receives the external message, it will have the first transaction). The sequence of transactions forms a chain. So you can see that each smart contract has its own transactions, which means that each contract has its own `little blockchain` (you can read more about it [here](/learn/overviews/ton-blockchain)), so the network can process the transactions due to this completely independent of each other
+
+## The difference of Gas system
+
+In Ethereum, the cost of a transaction is measured in `gas`, which reflects the amount of computing resources required for the transaction. The `gas` cost is divided into a `base fee` set by the protocol and a `priority fee` that the user adds to speed up transaction processing by validators. The `total fee` will be = `units of gas used` * (`base fee` + `priority fee`).
+Additionally, storage in Ethereum is essentially free, meaning that once data is stored on the blockchain, there is no ongoing cost for keeping it there.
+
+In TON, the calculation of transaction fees is complex and includes several types of fees: for storing smart contracts in the blockchain, for importing messages into the blockchain, for executing code on a virtual machine, for processing actions after code execution, and for sending messages outside the TON blockchain. The price of gas and some other parameters can be changed by voting on the main network. Unlike Ethereum, TON users cannot set the gas price themselves. Also, the developer needs to return the remaining gas funds to the owner manually, otherwise they will remain locked. The use of smart contract storage also affects the price: if a wallet's smart contract has not been used for a long time, the next transaction will cost more.
diff --git a/docs/develop/ethereum-to-ton/solidity-vs-func.md b/docs/develop/ethereum-to-ton/solidity-vs-func.md
new file mode 100644
index 0000000000..3dbd92fd81
--- /dev/null
+++ b/docs/develop/ethereum-to-ton/solidity-vs-func.md
@@ -0,0 +1,222 @@
+# Solidity vs FunC
+
+Smart contract development involves usage of predefined languages such as Solidity for Ethereum, and FunC for TON.
+Solidity is an object-oriented, high-level, strictly-typed language influenced by C++, Python, and JavaScript, and is specifically designed for writing smart contracts that execute on Ethereum blockchain platforms.
+
+FunC is also a high-level language, used to program smart contracts on TON Blockchain, being a domain-specific, C-like, statically-typed language.
+
+In the sections below will be analysed briefly the following aspects of these languages, i.e. data types, storage, functions, flow control structures and dictionaries (hashmaps).
+
+## Storage layout
+
+Solidity provides a flat storage model, which means that all state variables are stored in a single, continuous block of memory called the storage. The storage is a key-value store where each key is a 256-bit (32-byte) integer that represents the storage slot number, and each value is the 256-bit word stored at that slot. The slots are numbered sequentially starting from zero, and each slot can store a single word. Solidity allows the programmer to specify the storage layout by using the storage keyword to define state variables. The order in which the variables are defined determines their position in the storage.
+
+Permanent storage data in TON Blockchain is stored as a cell. Cells play the role of memory in the stack-based TVM. A cell can be transformed into a slice, and then the data bits and references to other cells from the cell can be obtained by loading them from the slice. Data bits and references to other cells can be stored into a builder, and then the builder can be finalised into a new cell.
+
+## Data types
+
+Solidity includes the following basic data types:
+- Signed/Unsigned integers
+- Boolean
+- Addresses – used to store Ethereum wallet or smart contract addresses, typically around 20 bytes. An address type can be suffixed with the keyword “payable”, which restricts it to store only wallet addresses and use the transfer and send crypto functions.
+- Byte arrays – declared with the keyword “bytes”, is a fixed-size array used to store a predefined number of bytes up to 32, usually declared along with the keyword.
+- Literals – Immutable values such as addresses, rationals and integers, strings, unicode and hexadecimals, which can be stored in a variable.
+- Enums
+- Arrays (fixed/dynamic)
+- Structs
+- Mappings
+
+
+In case of FunC, the main data types are:
+- Integers
+- Cell – basic for TON opaque data structure, which contains up to 1,023 bits and up to 4 references to other cells
+- Slice and Builder – special objects to read from and write to cells,
+- Continuation – another flavour of cell that contains ready-to-execute TVM byte-code
+- Tuples – is an ordered collection of up to 255 components, having arbitrary value types, possibly distinct.
+- Tensors – is an ordered collection ready for mass assigning like: (int, int) a = (2, 4). A special case of tensor type is the unit type (). It represents that a function doesn’t return any value, or has no arguments.
+
+Currently, FunC has no support for defining custom types.
+
+### See Also
+
+- [Statements](/develop/func/statements)
+
+## Declaring and using variables
+
+Solidity is a statically typed language, which means that the type of each variable must be specified when it is declared.
+
+```js
+uint test = 1; // Declaring an unsigned variable of integer type
+bool isActive = true; // Logical variable
+string name = "Alice"; // String variable
+```
+
+FunC is a more abstract and function-oriented language, it supports dynamic typing and functional programming style.
+
+```func
+(int x, int y) = (1, 2); // A tuple containing two integer variables
+var z = x + y; // Dynamic variable declaration
+```
+
+### See Also
+
+- [Statements](/develop/func/statements)
+
+## Loops
+
+Solidity supports `for`, `while`, and `do { ... } while` loops.
+
+If you want to do something 10 times, you can do it this way:
+
+```js
+uint x = 1;
+
+for (uint i; i < 10; i++) {
+ x *= 2;
+}
+
+// x = 1024
+```
+
+FunC in turn supports `repeat`, `while`, and `do { ... } until` loops. The for loop is not supported. If you want to execute the same code as in the example above on Func, you can use `repeat`
+
+```func
+int x = 1;
+repeat(10) {
+ x *= 2;
+}
+;; x = 1024
+```
+
+### See Also
+
+- [Statements](/develop/func/statements)
+
+## Functions
+
+Solidity approaches function declarations with a blend of clarity and control. In this programming language, each function is initiated with the keyword "function," followed by the name of the function and its parameters. The body of the function is enclosed within curly braces, clearly defining the operational scope. Additionally, return values are indicated using the "returns" keyword. What sets Solidity apart is its categorization of function visibility—functions can be designated as `public`, `private`, `internal`, or `external`, dictating the conditions under which they can be accessed and called by other parts of the contract or by external entities. Below is an example in which we set the global variable `num` in the Solidity language:
+
+```js
+function set(uint256 _num) public returns (bool) {
+ num = _num;
+ return true;
+}
+```
+
+Transitioning to FunC, FunC program is essentially a list of function declarations/definitions and global variable declarations. A FunC function declaration typically starts with an optional declarator, followed by the return type and the function name. Parameters are listed next, and the declaration ends with a selection of specifiers—such as `impure`, `inline/inline_ref`, and `method_id`. These specifiers adjust the function's visibility, its ability to modify contract storage, and its inlining behavior. Below is an example in which we stores storage variable as a cell into persistent storage in the Func language:
+
+```func
+() save_data(int num) impure inline {
+ set_data(begin_cell()
+ .store_uint(num, 32)
+ .end_cell()
+ );
+}
+```
+
+### See Also
+
+- [Functions](/develop/func/functions)
+
+## Flow control structures
+
+Most of the control structures known from curly-braces languages are available in Solidity, including: `if`, `else`, `while`, `do`, `for`, `break`, `continue`, `return`, with the usual semantics known from C or JavaScript.
+
+FunC supports classic `if-else` statements, as well as `ifnot`, `repeat`, `while` and `do/until` loops. Also since v0.4.0 `try-catch` statements are supported.
+
+### See Also
+
+- [Statements](/develop/func/statements)
+
+## Dictionaries
+
+Dictionary (hashmap/mapping) data structure is very important for Solidity and FunC contract development because it allows developers to efficiently store and retrieve data in smart contracts, specifically data related to a specific key, such as a user’s balance or ownership of an asset.
+
+Mapping is a hash table in Solidity that stores data as key-value pairs, where the key can be any of the built-in data types, excluding reference types, and the value of the data type can be any type. Mappings are most typically used in Solidity and the Ethereum blockchain to connect a unique Ethereum address to a corresponding value type. In any other programming language, a mapping is equivalent to a dictionary.
+
+In Solidity, mappings do not have a length, nor do they have the concept of setting a key or a value. Mappings are only applicable to state variables that serve as store reference types. When mappings are initialised, they include every possible key, and are mapped to values whose byte-representations are all zeros.
+
+An analogy of mappings in FunC are dictionaries, or TON hashmaps. In the context of TON, a hashmap is a data structure represented by a tree of cells. Hashmap maps keys to values of arbitrary type so that quick lookup and modification are possible. The abstract representation of a hashmap in TVM is a Patricia tree, or a compact binary trie. Working with potentially large cell trees can create several problems. Each update operation builds an appreciable number of cells (each cell built costs 500 gas), which means that these operations can run out of resource if used carelessly. To avoid exceeding the gas limit, limit the number of dictionary updates in a single transaction. Also, a binary tree for `N` key-value pairs contains `N-1` forks, which means a total of at least `2N-1` cells. The storage of a smart contract is limited to `65536` unique cells, so the maximum number of entries in the dictionary is `32768`, or slightly more if there are repeating cells.
+
+### See Also
+
+- [Dictionaries in TON](/develop/func/dictionaries)
+
+## Smart-contract communication
+
+Solidity and FunC provide different approaches to interacting with smart contracts. The main difference lies in the mechanisms of invocation and interaction between contracts.
+
+Solidity uses an object-oriented approach where contracts interact with each other through method calls. This is similar to method calls in traditional object-oriented programming languages.
+
+```js
+// External contract interface
+interface IReceiver {
+ function receiveData(uint x) external;
+}
+
+contract Sender {
+ function sendData(address receiverAddress, uint x) public {
+ IReceiver receiver = IReceiver(receiverAddress);
+ receiver.receiveData(x); // Direct call of the contract function
+ }
+}
+```
+
+FunC, used in the TON blockchain ecosystem, operates on messages to invoke and interact between smart-contracts. Instead of calling methods directly, contracts send messages to each other, which can contain data and code for execution.
+
+Consider an example where a smart contract sender must send a message with a number, and a smart contract receiver must receive that number and perform some manipulation on it.
+
+Initially, the smart contract recipient must describe how it will receive messages.
+
+```func
+() recv_internal(int my_balance, int msg_value, cell in_msg, slice in_msg_body) impure {
+ int op = in_msg_body~load_uint(32);
+
+ if (op == 1) {
+ int num = in_msg_body~load_uint(32);
+ ;; do some manipulations
+ return ();
+ }
+
+ if (op == 2) {
+ ;;...
+ }
+}
+```
+
+Let's discuss in more detail what receiving a message looks like in our destination contract:
+1. `recv_internal()` - this function is executed when a contract is accessed directly within the blockchain. For example, when a contract accesses our contract.
+2. The function accepts amount of the contract balance, the amount of the incoming message, the cell with the original message and the `in_msg_body` slice, which stores only the body of the received message.
+3. Our message body will store two integer numbers. The first number is a 32-bit unsigned integer `op`, identifying the `operation` to be performed, or the `method` of the smart contract to be invoked. You can draw some analogy with Solidity and think of `op` as a function signature. The second number is the number we need to perform some manipulations with.
+4. To read from the resulting slice `op` and `our number`, we use `load_uint()`.
+5. Next, we manipulate the number (we omitted this functionality in this example).
+
+Next, the sender's smart contract is to send the message correctly. This is accomplished with`send_raw_message`, which expects a serialized message as an argument.
+
+```func
+int num = 10;
+cell msg_body_cell = begin_cell().store_uint(1,32).store_uint(num,32).end_cell();
+
+var msg = begin_cell()
+ .store_uint(0x18, 6)
+ .store_slice("EQBIhPuWmjT7fP-VomuTWseE8JNWv2q7QYfsVQ1IZwnMk8wL"a) ;; in the example, we just hardcode the recipient's address
+ .store_coins(0)
+ .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1)
+ .store_ref(msg_body_cell)
+ .end_cell();
+
+send_raw_message(msg, mode);
+```
+Let's discuss in more detail what it looks like for our smart contract to send a message to our recipient:
+1. Initially, we need to build our message. The full structure of the send can be found [here](develop/smart-contracts/messages). We won't go into detail on how to assemble it here, you can read about that at the link.
+2. The body of the message represents a cell. In `msg_body_cell` we do: `begin_cell()` - creates `Builder` for the future cell, first `store_uint` - stores the first uint into `Builder` (1 - this is our `op`), second `store_uint` - stores the second uint into `Builder` (num - this is our number that we will manipulate in the receiving contract), `end_cell()` - creates the cell.
+3. To attach the body that will come in `recv_internal` in the message, we reference the collected cell in the message itself with `store_ref`.
+4. Sending a message.
+
+This example presented how smart contracts can communicate with each other.
+
+### See Also
+
+- [Internal Messages](/develop/smart-contracts/guidelines/internal-messages)
+- [Sending Messages](/develop/smart-contracts/messages)
+- [Non-bouncable messages](develop/smart-contracts/guidelines/non-bouncable-messages)
diff --git a/docs/develop/ethereum-to-ton/tvm-vs-evm.md b/docs/develop/ethereum-to-ton/tvm-vs-evm.md
new file mode 100644
index 0000000000..9f52e64271
--- /dev/null
+++ b/docs/develop/ethereum-to-ton/tvm-vs-evm.md
@@ -0,0 +1,121 @@
+# TVM vs EVM
+
+Ethereum Virtual Machine (EVM) and TON Virtual Machine (TVM) are both stack-based virtual machines developed for running smart contract code. Although they have common features, there are notable distinctions between them.
+
+## Data presentation
+
+### Ethereum Virtual Machine (EVM)
+1. Fundamental Data Units
+ - The EVM operates primarily on 256-bit integers, reflecting its design around Ethereum's cryptographic functions (e.g., Keccak-256 hashing and elliptic curve operations).
+ - Data types are limited mainly to integers, bytes, and occasionally arrays of these types, but all must conform to 256-bit processing rules.
+2. State Storage
+- The entire state of the Ethereum blockchain is a mapping of 256-bit addresses to 256-bit values. This mapping is maintained in a data structure known as the Merkle Patricia Trie (MPT).
+- The MPT enables Ethereum to efficiently prove the consistency and integrity of the blockchain state through cryptographic verification, which is vital for a decentralized system like Ethereum.
+3. Data Structure Limitations
+- The simplification to 256-bit word constraints means that the EVM is not inherently designed to handle complex or custom data structures directly.
+- Developers often need to implement additional logic within smart contracts to simulate more complex data structures, which can lead to increased gas costs and complexity.
+
+### TON Virtual Machine (TVM)
+1. Cell-Based Architecture
+- TVM uses a unique "bag of cells" model to represent data. Each cell can contain up to 128 data bytes and can have up to 4 references to other cells.
+- This structure allows the TVM to natively support arbitrary algebraic data types and more complex constructions such as trees or directed acyclic graphs (DAGs) directly within its storage model.
+2. Flexibility and Efficiency
+- The cell model provides significant flexibility, enabling the TVM to handle a wide variety of data structures more naturally and efficiently than the EVM.
+- For example, the ability to create linked structures through cell references allows for dynamic and potentially infinite data structures, which are crucial for certain types of applications like decentralized social networks or complex decentralized finance (DeFi) protocols.
+3. Complex Data Handling
+- The ability to manage complex data types inherently within the VM architecture reduces the need for workaround implementations in smart contracts, potentially lowering the execution cost and increasing execution speed.
+- TVM's design is particularly advantageous for applications requiring complex state management or interlinked data structures, providing a robust foundation for developers to build sophisticated and scalable decentralized applications.
+
+## Stack machine
+
+### Ethereum Virtual Machine (EVM)
+
+- The EVM operates as a traditional stack-based machine, where it uses a last-in, first-out (LIFO) stack to manage computation.
+- It processes operations by pushing and popping 256-bit integers, which are the standard size for all elements in the stack.
+
+### TON Virtual Machine (TVM)
+
+- TVM also functions as a stack-based machine but with a key distinction: it supports both 257-bit integers and references to cells.
+- This allows TVM to push and pop these two distinct types of data onto/from the stack, providing enhanced flexibility in direct data manipulation.
+
+### Example of stack operations
+
+Suppose we want to add two numbers (2 and 2) in EVM. The process would involve pushing the numbers onto the stack and then calling the `ADD` instruction. The result (4) would be left on the top of the stack.
+
+We can do this operation in the same way in TVM. But let’s look at another example with more complex data structures, such as hashmaps and cell reference. Suppose we have a hashmap that stores key-value pairs, where keys are integers and values are either integers or cell references. Let’s say our hashmap contains the following entries:
+
+```js
+{
+ 1: 10
+ 2: cell_a (which contains 10)
+}
+```
+
+We want to add the values associated with keys 1 and 2 and store the result with key 3. Let’s look at stack operations:
+
+1. Push key 1 onto the stack: `stack` = (1)
+2. Call `DICTGET` for key 1 (retrieves the value associated with the key at the top of the stack): Retrieves value 10. `stack` = (10)
+3. Push key 2 onto the stack: `stack` = (10, 2)
+4. Call `DICTGET` for key 2: Retrieves reference to Cell_A. `stack` = (10, Cell_A)
+5. Load value from Cell_A: An instruction to load the value from the cell reference is executed. `stack` = (10, 10)
+6. Call the `ADD` instruction: When the `ADD` instruction is executed, the TVM will pop the top two elements from the stack, add them together, and push the result back onto the stack. In this case, the top two elements are 10 and 10. After the addition, the stack will contain the result: `stack` = (20)
+7. Push key 3 onto the stack: `stack` = (20, 3)
+8. Call `DICTSET`: Stores 20 with key 3. Updated hashmap:
+
+```js
+{
+ 1: 10,
+ 2: cell_a,
+ 3: 20
+}
+```
+
+To do the same in EVM, we need to define a mapping that stores key-value pairs and the function where we work directly with 256-bit integers stored in the mapping.
+It’s essential to note that the EVM supports complex data structures by leveraging Solidity, but these structures are built on top of the EVM’s simpler data model, which is fundamentally different from the more expressive data model of the TVM
+
+## Arithmetic operations
+
+### Ethereum Virtual Machine (EVM)
+
+- The Ethereum Virtual Machine (EVM) handles arithmetic using 256-bit integers, meaning operations such as addition, subtraction, multiplication, and division are tailored to this data size.
+
+### TON Virtual Machine (TVM)
+
+- The TON Virtual Machine (TVM) supports a more diverse range of arithmetic operations, including 64-bit, 128-bit, and 256-bit integers, both unsigned and signed, as well as modulo operations. TVM further enhances its arithmetic capabilities with operations like multiply-then-shift and shift-then-divide, which are particularly useful for implementing fixed-point arithmetic. This variety allows developers to select the most efficient arithmetic operations based on the specific requirements of their smart contracts, offering potential optimizations based on data size and type.
+
+## Overflow checks
+
+### Ethereum Virtual Machine (EVM)
+
+- In the EVM, overflow checks are not inherently performed by the virtual machine itself. With the introduction of Solidity 0.8.0, automatic overflow and underflow checks were integrated into the language to enhance security. These checks help prevent common vulnerabilities related to arithmetic operations but require newer versions of Solidity, as earlier versions necessitate manual implementation of these safeguards.
+
+### TON Virtual Machine (TVM)
+
+- In contrast, TVM automatically performs overflow checks on all arithmetic operations, a feature built directly into the virtual machine. This design choice simplifies the development of smart contracts by inherently reducing the risk of errors and enhancing the overall reliability and security of the code.
+
+## Cryptography and hash functions
+
+### Ethereum Virtual Machine (EVM)
+
+- EVM has support for the Ethereum-specific cryptography scheme, such as the secp256k1 elliptic curve and the keccak256 hash function. Also, EVM does not have built-in support for Merkle proofs, which are cryptographic proofs used to verify the membership of an element in a set.
+
+### TON Virtual Machine (TVM)
+
+- TVM offers support for 256-bit Elliptic Curve Cryptography (ECC) for predefined curves, like Curve25519. It also supports Weil pairings on some elliptic curves, which are useful for fast implementation of zk-SNARKs (zero-knowledge proofs). Popular hash functions like sha256 are also supported, providing more options for cryptographic operations. In addition, TVM can work with Merkle proofs, providing additional cryptographic features that can be beneficial for certain use cases, such as verifying the inclusion of a transaction in a block.
+
+## High-level languages
+
+### Ethereum Virtual Machine (EVM)
+
+- EVM primarily uses Solidity as its high-level language, which is an object-oriented, statically-typed language similar to JavaScript and C++. Also, there are other languages for writing Ethereum smart-contracts such as Vyper, Yul, etc.
+
+### TON Virtual Machine (TVM)
+
+- TVM uses FunC as a high-level language designed for writing TON smart contracts. It is a procedural language with static types and support for algebraic data types. FunC compiles to Fift, which in turn compiles to TVM bytecode.
+
+## Conclusion
+
+In summary, while both EVM and TVM are stack-based machines designed to execute smart contracts, TVM offers more flexibility, support for a wider range of data types and structures, built-in overflow checks, advanced cryptographic features.
+
+TVM’s support for sharding-aware smart contracts and its unique data representation approach make it better suited for certain use cases and scalable blockchain networks.
+
diff --git a/docs/develop/fift/overview.mdx b/docs/develop/fift/overview.mdx
index c6d272f65b..43180c5bfc 100644
--- a/docs/develop/fift/overview.mdx
+++ b/docs/develop/fift/overview.mdx
@@ -15,20 +15,29 @@ hello world ok
Usually, using the Fift is not required for programming smart contracts in TON. However, Sometimes, you may need to use the Fift language to solve uncommon technical challenges as part of your task.
:::
+````mdx-code-block
+````
Introduction To Fift
-
+````
+````mdx-code-block
+
- His majesty Fift
+````
+His majesty Fift
+````mdx-code-block
+````
## Documentation
* [Fift: A Brief Introduction](https://ton.org/fiftbase.pdf)
-* [TON Virtual Machine](https://docs.ton.org/tvm.pdf)
+* [TON Virtual Machine](/learn/tvm-instructions/tvm-overview)
## Examples
diff --git a/docs/develop/func/cookbook.md b/docs/develop/func/cookbook.md
index 05af6b9462..39c840239e 100644
--- a/docs/develop/func/cookbook.md
+++ b/docs/develop/func/cookbook.md
@@ -2,9 +2,10 @@
The core reason for creating the FunC Cookbook is to collect all the experience from FunC developers in one place so that future developers will use it!
-Compared to the FunC Documentation, this article is more focused on everyday tasks every FunC developer resolve during the development of smart contracts.
+Compared to the [FunC Documentation](/develop/func/types), this article is more focused on everyday tasks every FunC developer resolve during the development of smart contracts.
## Basics
+
### How to write an if statement
Let's say we want to check if any event is relevant. To do this, we use the flag variable. Remember that in FunC `true` is `-1` and `false` is `0`.
@@ -107,7 +108,7 @@ Before working with `slice`, it is necessary to check whether it has any data to
```func
;; creating empty slice
slice empty_slice = "";
-;; `slice_empty?()` returns `true`, because slice dosen't have any `bits` and `refs`
+;; `slice_empty?()` returns `true`, because slice doesn't have any `bits` and `refs`
empty_slice.slice_empty?();
;; creating slice which contains bits only
@@ -147,14 +148,14 @@ slice_with_bits_and_refs.slice_empty?();
> ["begin_parse()" in docs](/develop/func/stdlib#begin_parse)
-### How to determine if slice is empty (dosen't have any bits, but may have refs)
+### How to determine if slice is empty (doesn't have any bits, but may have refs)
If we need to check only the `bits` and it does not matter if there are any `refs` in `slice`, then we should use `slice_data_empty?()`.
```func
;; creating empty slice
slice empty_slice = "";
-;; `slice_data_empty?()` returns `true`, because slice dosen't have any `bits`
+;; `slice_data_empty?()` returns `true`, because slice doesn't have any `bits`
empty_slice.slice_data_empty?();
;; creating slice which contains bits only
@@ -167,7 +168,7 @@ slice slice_with_refs_only = begin_cell()
.store_ref(null())
.end_cell()
.begin_parse();
-;; `slice_data_empty?()` returns `true`, because slice dosen't have any `bits`
+;; `slice_data_empty?()` returns `true`, because slice doesn't have any `bits`
slice_with_refs_only.slice_data_empty?();
;; creating slice which contains bits and refs
@@ -195,19 +196,19 @@ slice_with_bits_and_refs.slice_data_empty?();
> ["begin_parse()" in docs](/develop/func/stdlib#begin_parse)
-### How to determine if slice is empty (dosen't have any refs, but may have bits)
+### How to determine if slice is empty (doesn't have any refs, but may have bits)
In case we are only interested in `refs`, we should check their presence using `slice_refs_empty?()`.
```func
;; creating empty slice
slice empty_slice = "";
-;; `slice_refs_empty?()` returns `true`, because slice dosen't have any `refs`
+;; `slice_refs_empty?()` returns `true`, because slice doesn't have any `refs`
empty_slice.slice_refs_empty?();
;; creating slice which contains bits only
slice slice_with_bits_only = "Hello, world!";
-;; `slice_refs_empty?()` returns `true`, because slice dosen't have any `refs`
+;; `slice_refs_empty?()` returns `true`, because slice doesn't have any `refs`
slice_with_bits_only.slice_refs_empty?();
;; creating slice which contains refs only
@@ -244,7 +245,7 @@ slice_with_bits_and_refs.slice_refs_empty?();
### How to determine if cell is empty
-To check if there is any data in a `cell`, we should first convert it to `slice`. If we are only interested in having `bits`, we should use `slice_data_empty?()`, if only `refs` - `slice_data_refs?()`. In case we want to check the presence of any data regardless of whether it is a `bit` or `ref`, we need to use `slice_empty?()`.
+To check if there is any data in a `cell`, we should first convert it to `slice`. If we are only interested in having `bits`, we should use `slice_data_empty?()`, if only `refs` - `slice_refs_empty?()`. In case we want to check the presence of any data regardless of whether it is a `bit` or `ref`, we need to use `slice_empty?()`.
```func
cell cell_with_bits_and_refs = begin_cell()
@@ -278,7 +279,7 @@ else {
### How to determine if dict is empty
-There is a method of `dict_empty?()` to check the date presence in dict. This method is the equivalent of `cell_null?()` because usually a `null`-cell is an empty dictionary.
+There is a method of `dict_empty?()` to check the data presence in dict. This method is the equivalent of `cell_null?()` because usually a `null`-cell is an empty dictionary.
```func
cell d = new_dict();
@@ -402,7 +403,7 @@ cell msg = begin_cell()
.store_uint(0x18, 6)
.store_slice(addr)
.store_coins(amount)
- .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1)
+ .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1) ;; default message headers (see sending messages page)
.store_uint(op, 32)
.end_cell();
@@ -451,7 +452,7 @@ cell msg = begin_cell()
.store_uint(0x18, 6)
.store_slice(addr)
.store_coins(amount)
- .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1)
+ .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1) ;; default message headers (see sending messages page)
.store_uint(1, 1) ;; set bit to 1 to indicate that the cell will go on
.store_ref(message_body)
.end_cell();
@@ -500,7 +501,7 @@ cell msg = begin_cell()
.store_uint(0x18, 6)
.store_slice(addr)
.store_coins(amount)
- .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1)
+ .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1) ;; default message headers (see sending messages page)
.store_uint(op, 32)
.store_slice(message_body)
.end_cell();
@@ -734,7 +735,7 @@ if (current_time > 1672080143) {
:::caution draft
Please note that this method of generating random numbers isn't safe.
-TODO: add link to an article about generating random numbers
+Checkout [Random Number Generation](https://docs.ton.org/develop/smart-contracts/guidelines/random-number-generation) for more information.
:::
```func
@@ -1081,7 +1082,7 @@ cell msg = begin_cell()
.store_uint(0x18, 6) ;; flags
.store_slice("EQBIhPuWmjT7fP-VomuTWseE8JNWv2q7QYfsVQ1IZwnMk8wL"a) ;; destination address
.store_coins(100) ;; amount of nanoTons to send
- .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1) ;; 107 zero-bits
+ .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1) ;; default message headers (see sending messages page)
.store_uint(0, 32) ;; zero opcode - means simple transfer message with comment
.store_slice("Hello from FunC!") ;; comment
.end_cell();
@@ -1111,7 +1112,7 @@ The contract example below is useful to us if we need to perform any actions bet
.store_uint(0x18, 6)
.store_slice(addr)
.store_coins(100) ;; just for example
- .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1)
+ .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1) ;; default message headers (see sending messages page)
.store_slice(body)
.end_cell();
send_raw_message(msg, mode);
@@ -1133,7 +1134,7 @@ cell msg = begin_cell()
.store_uint(0x18, 6) ;; flags
.store_slice("EQBIhPuWmjT7fP-VomuTWseE8JNWv2q7QYfsVQ1IZwnMk8wL"a) ;; destination address
.store_coins(0) ;; we don't care about this value right now
- .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1) ;; 107 zero-bits
+ .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1) ;; default message headers (see sending messages page)
.store_uint(0, 32) ;; zero opcode - means simple transfer message with comment
.store_slice("Hello from FunC!") ;; comment
.end_cell();
@@ -1173,7 +1174,7 @@ cell msg = begin_cell()
;; We use literal `a` to get valid address inside slice from string containing address
.store_slice("EQBIhPuWmjT7fP-VomuTWseE8JNWv2q7QYfsVQ1IZwnMk8wL"a) ;; destination address
.store_coins(100) ;; amount of nanoTons to send
- .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1) ;; 106 zero-bits, necessary for internal messages
+ .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1) ;; default message headers (see sending messages page)
.store_uint(1, 1) ;; we want to store body as a ref
.store_ref(body)
.end_cell();
@@ -1486,3 +1487,74 @@ forall X -> (tuple, (X)) pop_back (tuple t) asm "UNCONS";
.end_cell();
}
```
+
+### How to update the smart contract logic
+
+Below is a simple `СounterV1` smart-contract that has the functionality to increment the counter and update the smart-contract logic.
+
+```func
+() recv_internal (slice in_msg_body) {
+ int op = in_msg_body~load_uint(32);
+
+ if (op == op::increase) {
+ int increase_by = in_msg_body~load_uint(32);
+ ctx_counter += increase_by;
+ save_data();
+ return ();
+ }
+
+ if (op == op::upgrade) {
+ cell code = in_msg_body~load_ref();
+ set_code(code);
+ return ();
+ }
+}
+```
+
+After operating the smart-contract, you realize that you are missing the meter reduction feature. You must copy the code of the smart-contract `CounterV1` and next to the `increase` function, add a new `decrease` function. Now your code looks like this:
+
+```func
+() recv_internal (slice in_msg_body) {
+ int op = in_msg_body~load_uint(32);
+
+ if (op == op::increase) {
+ int increase_by = in_msg_body~load_uint(32);
+ ctx_counter += increase_by;
+ save_data();
+ return ();
+ }
+
+ if (op == op::decrease) {
+ int decrease_by = in_msg_body~load_uint(32);
+ ctx_counter -= increase_by;
+ save_data();
+ return ();
+ }
+
+ if (op == op::upgrade) {
+ cell code = in_msg_body~load_ref();
+ set_code(code);
+ return ();
+ }
+}
+```
+
+Once the smart-contract `CounterV2` is ready, you must compile it off-chain into a `cell` and send an upgrade message to the `CounterV1` smart-contract.
+
+```javascript
+await contractV1.sendUpgrade(provider.sender(), {
+ code: await compile('ContractV2'),
+ value: toNano('0.05'),
+});
+```
+
+> 💡 Useful links
+>
+> [Is it possible to re-deploy code to an existing address or does it have to be deployed as a new contract?](/develop/howto/faq#is-it-possible-to-re-deploy-code-to-an-existing-address-or-does-it-have-to-be-deployed-as-a-new-contract)
+>
+> ["set_code()" in docs](/develop/func/stdlib#set_code)
+
+
+
+
+
diff --git a/docs/develop/func/dictionaries.md b/docs/develop/func/dictionaries.md
new file mode 100644
index 0000000000..712a588208
--- /dev/null
+++ b/docs/develop/func/dictionaries.md
@@ -0,0 +1,81 @@
+# Dictionaries in TON
+
+Smart contracts can make use of dictionaries - ordered key-value mappings. They are represented by trees of cells internally.
+
+:::warning
+Working with potentially large trees of cells creates a couple of considerations:
+
+1. Every update operation builds a notable amount of cells (and each built cell costs 500 gas, as may be found on [TVM Instructions](/learn/tvm-instructions/instructions#gas-prices) page), meaning that those operations may run out of gas if used without care.
+ - In particular, Wallet bot has run into such a problem once, when using highload-v2 wallet. The unbounded loop combined with expensive dictionary updates on each iteration led to gas running out and eventually to repeated transactions like [fd78228f352f582a544ab7ad7eb716610668b23b88dae48e4f4dbd4404b5d7f6](https://tonviewer.com/transaction/fd78228f352f582a544ab7ad7eb716610668b23b88dae48e4f4dbd4404b5d7f6) draining its balance.
+2. The binary tree for N key-value pairs contains N-1 forks, and thus at least 2N-1 cells in total. Smart contract storage is limited to 65536 unique cells, so maximum number of entries in dictionary is 32768 or slightly more if there are repeated cells.
+:::
+
+## Dictionary kinds
+
+### "Hash"map
+
+Evidently, the most known and used kind of dictionaries in TON is hashmap. It has a whole section worth of TVM opcodes ([TVM Instructions](/learn/tvm-instructions/instructions#quick-search) - Dictionary Manipulation) and is commonly used in smart contracts.
+
+Those dictionaries are mappings of same-length keys (said length is provided as argument to all functions) to value slices. Contrary to "hash" in name, entries there are ordered and offer cheap extraction of element by key, previous or next key-value pair. Values are placed in the same cell as internal node tags and possibly key parts, so they can't use all 1023 bits; `~udict_set_ref` is commonly used in such a situation.
+
+Empty hashmap is represented as `null` by TVM; thus, it is not a cell. To store dictionary in a cell, one first saves one bit (0 for empty, 1 otherwise), and then adds reference if hashmap is not empty. Thus, `store_maybe_ref` and `store_dict` are interchangeable, and some smart contract authors use `load_dict` to load a `Maybe ^Cell` from incoming message or storage.
+
+Possible operations for hashmaps:
+- load from slice, store to builder
+- get/set/delete value by key
+- replace value (set new value if key was already present) / add one (if key was not present)
+- move to next/previous key-value pair, in order of keys (this can be used to [iterate over dictionaries](https://docs.ton.org/develop/func/cookbook#how-to-iterate-dictionaries) if gas limit is not a concern)
+- retrieve minimal/maximal key with its value
+- get function (continuation) by key and immediately execute it
+
+In order for contract not to break of gas limit exceeding, only a limited number of dictionary updates should take place while processing one transaction. If contract's balance is used to maintain the map according to developer's conditions, the contract can send itself a message to continue cleanup.
+
+:::info
+There are instructions for retrieving a subdictionary: subset of entries within a given key range. Those have not been tested, so you can check them out only in TVM assembly form: `SUBDICTGET` and similar.
+:::
+
+#### Hashmap examples
+
+Let's see what hashmaps look like, looking specifically at mapping of 257-bit integer keys to empty value slices (such a map would only indicate presence or absence of element).
+
+A way to check that quickly is to run following script in Python (possibly replacing `pytoniq` with other SDK as appropriate):
+
+```python
+import pytoniq
+k = pytoniq.HashMap(257)
+em = pytoniq.begin_cell().to_slice()
+k.set(5, em)
+k.set(7, em)
+k.set(5 - 2**256, em)
+k.set(6 - 2**256, em)
+print(str(pytoniq.begin_cell().store_maybe_ref(k.serialize()).end_cell()))
+```
+
+The structure is binary tree, even a balanced one if we overlook the root cell.
+
+```
+1[80] -> {
+ 2[00] -> {
+ 265[9FC00000000000000000000000000000000000000000000000000000000000000080] -> {
+ 4[50],
+ 4[50]
+ },
+ 266[9FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF40] -> {
+ 2[00],
+ 2[00]
+ }
+ }
+}
+```
+
+There are [more examples on hashmap parsing](/develop/data-formats/tl-b-types#hashmap-parsing-example) in documentation.
+
+### Augmented maps (with additional data in each node)
+
+Those maps are used internally by TON validators in order to calculate total balance of all contracts in a shard (using maps with total subtree balance with each node allows them to validate updates very quickly). There are no TVM primitives for working with these.
+
+### Prefix dictionary
+
+:::info
+Testing reveals that insufficient documentation is there to create prefix dictionaries. You shouldn't use them in production contracts unless you have the full knowledge how the relevant opcodes, `PFXDICTSET` and similar, work.
+:::
diff --git a/docs/develop/func/functions.md b/docs/develop/func/functions.md
index d269897e3a..c509c91277 100644
--- a/docs/develop/func/functions.md
+++ b/docs/develop/func/functions.md
@@ -215,7 +215,17 @@ is defined. `impure` is used because `RANDU256` changes the internal state of th
#### Inline specifier
If a function has `inline` specifier, its code is actually substituted in every place where the function is called. It goes without saying that recursive calls to inlined functions are not possible.
-For example, you can using `inline` like this way in this example: [ICO-Minter.fc](https://github.com/ton-blockchain/token-contract/blob/f2253cb0f0e1ae0974d7dc0cef3a62cb6e19f806/ft/jetton-minter-ICO.fc#L16)
+For example,
+
+```func
+(int) add(int a, int b) inline {
+ return a + b;
+}
+```
+
+as the `add` function is marked with the `inline` specifier. The compiler will try to replace calls to `add` with the actual code `a + b`, avoiding the function call overhead.
+
+Here is another example of how you can use inline, taken from [ICO-Minter.fc](https://github.com/ton-blockchain/token-contract/blob/f2253cb0f0e1ae0974d7dc0cef3a62cb6e19f806/ft/jetton-minter-ICO.fc#L16):
```func
() save_data(int total_supply, slice admin_address, cell content, cell jetton_wallet_code) impure inline {
@@ -230,6 +240,7 @@ For example, you can using `inline` like this way in this example: [ICO-Minter.f
```
+
#### Inline_ref specifier
The code of a function with the `inline_ref` specifier is put into a separate cell, and every time when the function is called, a `CALLREF` command is executed by TVM. So it's similar to `inline`, but because a cell can be reused in several places without duplicating it, it is almost always more efficient in terms of code size to use `inline_ref` specifier instead of `inline` unless the function is called exactly once. Recursive calls of `inline_ref`'ed functions are still impossible because there are no cyclic references in the TVM cells.
#### method_id
diff --git a/docs/develop/func/overview.md b/docs/develop/func/overview.mdx
similarity index 52%
rename from docs/develop/func/overview.md
rename to docs/develop/func/overview.mdx
index ec8aa85fd1..62dcdd9af1 100644
--- a/docs/develop/func/overview.md
+++ b/docs/develop/func/overview.mdx
@@ -1,3 +1,5 @@
+import Button from '@site/src/components/button'
+
# Overview
A high-level language FunC is used to program smart contracts on TON.
@@ -21,11 +23,20 @@ FunC programs are compiled into Fift assembler code, which generates correspondi
Further this bytecode (actually a [tree of cells](/learn/overviews/cells), like any other data in TON Blockchain) can be used for creating smart contracts in the blockchain or can be run on a local instance of TVM.
-You can find more information about FunC in the [DOCUMENTATION](/develop/func/types) section.
-
-:::info
-FunC documentation was initially written by [@akifoq](https://github.com/akifoq).
-:::
+````mdx-code-block
+
+````
+FunC Cookbook
+````mdx-code-block
+
+````
+````mdx-code-block
+
+````
+FunC Documentation
+````mdx-code-block
+
+````
## Compiler
@@ -47,6 +58,37 @@ At the same time you can always make binaries from sources like:
[FunC compiler source code](https://github.com/ton-blockchain/ton/tree/master/crypto/func) (read [how to compile](/develop/howto/compile#func) a FunC compiler from sources).
:::
+## TON Course: FunC
+
+The [TON Blockchain Course](https://stepik.org/course/176754/) is a comprehensive guide to TON Blockchain development.
+
+Module 4 completely covers FunC language and smart contracts development.
+
+````mdx-code-block
+
+````
+Check TON Blockchain Course
+````mdx-code-block
+
+````
+````mdx-code-block
+
+````
+CHN
+````mdx-code-block
+
+````
+````mdx-code-block
+
+````
+RU
+````mdx-code-block
+
+````
+
## Tutorials
:::tip starter tip
@@ -55,6 +97,13 @@ The best place to start to develop using FunC: [INTRODUCTION](/develop/smart-con
Other materials gracefully provided by the experts from the community:
+- [TON Speed Run series](https://tonspeedrun.com/)
+ - [🚩 Challenge 1: Simple NFT Deploy](https://github.com/romanovichim/TONQuest1)
+ - [🚩 Challenge 2: Chatbot Contract](https://github.com/romanovichim/TONQuest2)
+ - [🚩 Challenge 3: Jetton Vending Machine](https://github.com/romanovichim/TONQuest3)
+ - [🚩 Challenge 4: Lottery/Raffle](https://github.com/romanovichim/TONQuest4)
+ - [🚩 Challenge 5: Create UI to interact with the contract in 5 minutes](https://github.com/romanovichim/TONQuest5)
+ - [🚩 Challenge 6: Analyzing NFT sales on the Getgems marketplace](https://github.com/romanovichim/TONQuest6)
* [Func & Blueprint](https://www.youtube.com/watch?v=7omBDfSqGfA&list=PLtUBO1QNEKwtO_zSyLj-axPzc9O9rkmYa) by **@MarcoDaTr0p0je**
* [Learn FunC in Y Minutes](https://learnxinyminutes.com/docs/func/) by **@romanovichim**
* [TON Hello World: Step-by-step guide for writing your first smart contract](https://ton-community.github.io/tutorials/02-contract/)
@@ -68,28 +117,17 @@ Other materials gracefully provided by the experts from the community:
Participating in [contests](https://t.me/toncontests) is a great way to learn FunC.
-You can also study previous competitions for learning purposes:
-* TON Smart Challenge #4 (best for getting started):
- [Contest Page](https://ton.org/ton-smart-challenge-4),
- [Tasks](https://github.com/ton-community/tsc4),
- [Solutions](/develop/smart-contracts/examples#ton-smart-challenge-4),
-
-* TON Smart Challenge #2 (good for getting started):
- [Contest Page](https://ton.org/ton-smart-challenge-2),
- [Tasks](https://github.com/ton-blockchain/func-contest2),
- [Solutions](https://github.com/ton-blockchain/func-contest2-solutions),
- [Tests](https://github.com/ton-blockchain/func-contest2-tests).
-
-* TON Smart Challenge #1 (good for beginners):
- [Contest Page](https://ton.org/contest),
- [Tasks](https://github.com/ton-blockchain/func-contest1),
- [Solutions](https://github.com/ton-blockchain/func-contest1-solutions),
- [Tests](https://github.com/ton-blockchain/func-contest1-tests).
-
-* TON Smart Challenge #3 (intermediate):
- [Contest Page](https://ton.org/en/ton-smart-challenge-3),
- [Tasks](https://github.com/ton-blockchain/func-contest3),
- [Solutions](https://github.com/nns2009/TON-FunC-contest-3).
+You can also study previous competitions for learning purposes.
+
+#### Contests Legacy
+
+| Contest Descr | Tasks | Solutions |
+|--------------------------|----------------------------------------------------------|------------------------------------------------------------------------|
+| TSC #5 (December, 2023) | [Tasks](https://github.com/ton-community/tsc5) | |
+| TSC #4 (September, 2023) | [Tasks](https://github.com/ton-community/tsc4) | [Solutions](/develop/smart-contracts/examples#ton-smart-challenge-4) |
+| TSC #3 (December, 2022) | [Tasks](https://github.com/ton-blockchain/func-contest3) | [Solutions](https://github.com/nns2009/TON-FunC-contest-3) |
+| TSC #2 (July, 2022) | [Tasks](https://github.com/ton-blockchain/func-contest2) | [Solutions](https://github.com/ton-blockchain/func-contest2-solutions) |
+| TSC #1 (March, 2022) | [Tasks](https://github.com/ton-blockchain/func-contest1) | [Solutions](https://github.com/ton-blockchain/func-contest1-solutions) |
## Smart contract examples
@@ -99,3 +137,5 @@ Standard basic smart contracts like wallets, electors (manages validation on TON
## Changelog
[History of funC updates](/develop/func/changelog).
+
+
diff --git a/docs/develop/func/stdlib.mdx b/docs/develop/func/stdlib.mdx
index b3bf5c8b68..753fe1f325 100644
--- a/docs/develop/func/stdlib.mdx
+++ b/docs/develop/func/stdlib.mdx
@@ -9,299 +9,440 @@ toc_max_heading_level: 6
This section discusses the [stdlib.fc](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/stdlib.fc) library with standard functions used in FunC.
:::
-
-Currently, the library is just a wrapper for the most common assembler of the TVM commands which are not built-in. Each TVM command description used in the library can be found in the [TVM documentation](https://ton.org/tvm.pdf) (appendix A). Some descriptions were borrowed for this document.
+Currently, the library is just a wrapper for the most common assembler of the TVM commands which are not built-in. Each TVM command description used in the library can be found in the [TVM documentation](/learn/tvm-instructions/tvm-overview) section. Some descriptions were borrowed for this document.
Some functions are commented out in the file. It means that they have already become built-ins for optimization purposes. However, the type signature and semantics remain the same.
Note that some less common commands are not presented in the stdlib. Someday they will also be added.
## Tuple manipulation primitives
+
The names and the types are mostly self-explaining. See [polymorhism with forall](/develop/func/functions#polymorphism-with-forall) for more info on the polymorphic functions.
Note that currently values of atomic type `tuple` cannot be cast into composite tuple types (e.g. `[int, cell]`) and vise versa.
### Lisp-style lists
+
Lists can be represented as nested 2-element tuples. Empty list is conventionally represented as TVM `null` value (it can be obtained by calling `null()`). For example, the tuple `(1, (2, (3, null)))` represents the list `[1, 2, 3]`. Elements of a list can be of different types.
+
#### cons
+
```func
forall X -> tuple cons(X head, tuple tail) asm "CONS";
```
+
Adds an element to the beginning of a lisp-style list.
+
#### uncons
+
```func
forall X -> (X, tuple) uncons(tuple list) asm "UNCONS";
```
+
Extracts the head and the tail of lisp-style list.
+
#### list_next
+
```func
forall X -> (tuple, X) list_next(tuple list) asm( -> 1 0) "UNCONS";
```
+
Extracts the head and tail of a lisp-style list. Can be used as a [(non-)modifying method](/develop/func/statements#methods-calls).
+
```func
() foo(tuple xs) {
- (_, int x) = xs.list_next(); ;; get the first element, `_` means do not use tail list
+ (_, int x) = xs.list_next(); ;; get the first element, `_` means do not use tail list
int y = xs~list_next(); ;; pop the first element
int z = xs~list_next(); ;; pop the second element
}
```
+
#### car
+
```func
forall X -> X car(tuple list) asm "CAR";
```
+
Returns the head of a lisp-style list.
+
#### cdr
+
```func
tuple cdr(tuple list) asm "CDR";
```
+
Returns the tail of a lisp-style list.
+
### Other tuple primitives
+
#### empty_tuple
+
```func
tuple empty_tuple() asm "NIL";
```
+
Creates 0-element tuple.
+
#### tpush
+
```func
forall X -> tuple tpush(tuple t, X value) asm "TPUSH";
forall X -> (tuple, ()) ~tpush(tuple t, X value) asm "TPUSH";
```
+
Appends the value `x` to the `Tuple t = (x1, ..., xn)` but only if the resulting `Tuple t' = (x1, ..., xn, x)` is no longer than 255 characters. Otherwise, a type check exception is thrown.
+
#### single
+
```func
forall X -> [X] single(X x) asm "SINGLE";
```
+
Creates a singleton, i.e., a tuple of length one.
+
#### unsingle
+
```func
forall X -> X unsingle([X] t) asm "UNSINGLE";
```
+
Unpacks a singleton.
+
#### pair
+
```func
forall X, Y -> [X, Y] pair(X x, Y y) asm "PAIR";
```
+
Creates a pair.
+
#### unpair
+
```func
forall X, Y -> (X, Y) unpair([X, Y] t) asm "UNPAIR";
```
+
Unpacks a pair.
+
#### triple
+
```func
forall X, Y, Z -> [X, Y, Z] triple(X x, Y y, Z z) asm "TRIPLE";
```
+
Creates a triple.
#### untriple
+
```func
forall X, Y, Z -> (X, Y, Z) untriple([X, Y, Z] t) asm "UNTRIPLE";
```
+
Unpacks a triple.
#### tuple4
+
```func
forall X, Y, Z, W -> [X, Y, Z, W] tuple4(X x, Y y, Z z, W w) asm "4 TUPLE";
```
+
Creates 4-element tuple.
#### untuple4
+
```func
forall X, Y, Z, W -> (X, Y, Z, W) untuple4([X, Y, Z, W] t) asm "4 UNTUPLE";
```
+
Unpacks 4-element tuple.
#### first
+
```func
forall X -> X first(tuple t) asm "FIRST";
```
+
Returns the first element of a tuple.
#### second
+
```func
forall X -> X second(tuple t) asm "SECOND";
```
+
Returns the second element of a tuple.
#### third
+
```func
forall X -> X third(tuple t) asm "THIRD";
```
+
Returns the third element of a tuple.
#### fourth
+
```func
forall X -> X fourth(tuple t) asm "3 INDEX";
```
+
Returns the fourth element of a tuple.
#### pair_first
+
```func
forall X, Y -> X pair_first([X, Y] p) asm "FIRST";
```
+
Returns the first element of a pair.
#### pair_second
+
```func
forall X, Y -> Y pair_second([X, Y] p) asm "SECOND";
```
+
Returns the second element of a pair.
#### triple_first
+
```func
forall X, Y, Z -> X triple_first([X, Y, Z] p) asm "FIRST";
```
+
Returns the first element of a triple.
#### triple_second
+
```func
forall X, Y, Z -> Y triple_second([X, Y, Z] p) asm "SECOND";
```
+
Returns the second element of a triple.
#### triple_third
+
```func
forall X, Y, Z -> Z triple_third([X, Y, Z] p) asm "THIRD";
```
+
Returns the third element of a triple.
## Domain specific primitives
+
### Extracting info from c7
+
Some useful information regarding smart contract invocation can be found in the [c7 special register](/learn/tvm-instructions/tvm-overview#control-registers). These primitives serve for convenient data extraction.
+
#### now
+
```func
int now() asm "NOW";
```
+
Returns the current Unix time as an Integer
+
#### my_address
+
```func
slice my_address() asm "MYADDR";
```
+
Returns the internal address of the current smart contract as a Slice with `MsgAddressInt`. If necessary, it can be parsed further using primitives such as `parse_std_addr`.
+
#### get_balance
+
```func
[int, cell] get_balance() asm "BALANCE";
```
+
Returns the remaining balance of the smart contract as `tuple` consisting of `int` (the remaining balance in nanotoncoins) and `cell` (a dictionary with 32-bit keys representing the balance of “extra currencies”). Note that RAW primitives such as `send_raw_message` do not update this field.
+
#### cur_lt
+
```func
int cur_lt() asm "LTIME";
```
+
Returns the logical time of the current transaction.
+
#### block_lt
+
```func
int block_lt() asm "BLOCKLT";
```
+
Returns the starting logical time of the current
block.
+
#### config_param
+
```func
cell config_param(int x) asm "CONFIGOPTPARAM";
```
+
Returns the value of the global configuration parameter with integer index `i` as `cell` or `null` value.
+
### Hashes
+
#### cell_hash
+
```func
int cell_hash(cell c) asm "HASHCU";
```
+
Computes the representation hash of `cell c` and returns it as a 256-bit unsigned integer `x`. Useful for signing and checking signatures of arbitrary entities represented by a tree of cells.
+
#### slice_hash
+
```func
int slice_hash(slice s) asm "HASHSU";
```
+
Computes the hash of `slice s` and returns it as a 256-bit unsigned integer `x`. The result is the same as if an ordinary cell containing only data and references from `s` had been created and its hash computed by `cell_hash`.
+
#### string_hash
+
```func
int string_hash(slice s) asm "SHA256U";
```
+
Computes sha256 of the data bits of `slice s`. If the bit length of `s` is not divisible by eight, it throws a cell underflow exception. The hash value is returned as a 256-bit unsigned integer `x`.
### Signature checks
+
#### check_signature
+
```func
int check_signature(int hash, slice signature, int public_key) asm "CHKSIGNU";
```
+
Checks the Ed25519 `signature` of `hash` (a 256-bit unsigned integer, usually computed as the hash of some data) using `public_key` (also represented by a 256-bit unsigned integer). The signature must contain at least 512 data bits; only the first 512 bits are used. If the signature is valid, the result is `-1`; otherwise, it is `0`. Note that `CHKSIGNU` creates a 256-bit slice with the hash and calls `CHKSIGNS`. That is, if `hash` is computed as the hash of some data, this data is hashed _twice_, the second hashing occurring inside `CHKSIGNS`.
+
#### check_data_signature
+
```func
int check_data_signature(slice data, slice signature, int public_key) asm "CHKSIGNS";
```
+
Checks whether `signature` is a valid Ed25519 signature of the data portion of `slice data` using `public_key`, similarly to `check_signature`. If the bit length of `data` is not divisible by eight, it throws a cell underflow exception. The verification of Ed25519 signatures is a standard one, with sha256 used to reduce `data` to the 256-bit number that is actually signed.
### Computation of boc size
+
The primitives below may be useful for computing storage fees for user-provided data.
+
#### compute_data_size?
+
```func
(int, int, int, int) compute_data_size?(cell c, int max_cells) asm "CDATASIZEQ NULLSWAPIFNOT2 NULLSWAPIFNOT";
```
+
Returns `(x, y, z, -1)` or `(null, null, null, 0)`. Recursively computes the count of distinct cells `x`, data bits `y`, and cell references `z` in the DAG rooted at `cell c`, effectively returning the total storage used by this DAG taking into account the identification of equal cells. The values of `x`, `y`, and `z` are computed by a depth-first traversal of this DAG with a hash table of visited cell hashes used to prevent visits of already-visited cells. The total count of visited cells `x` cannot exceed non-negative `max_cells`; otherwise, the computation is aborted before visiting the `(max_cells + 1)`-st cell and a zero flag is returned to indicate failure. If `c` is `null`, it returns `x = y = z = 0`.
+
#### slice_compute_data_size?
+
```func
(int, int, int, int) slice_compute_data_size?(slice s, int max_cells) asm "SDATASIZEQ NULLSWAPIFNOT2 NULLSWAPIFNOT";
```
+
Similar to `compute_data_size?` but accepting `slice s` instead of `cell`. The returned value of `x` does not take into account the cell that contains the slice `s` itself; however, the data bits and the cell references of `s` are accounted for in `y` and `z`.
+
#### compute_data_size
+
```func
(int, int, int) compute_data_size(cell c, int max_cells) impure asm "CDATASIZE";
```
+
A non-quiet version of `compute_data_size?` that throws a cell overflow exception (8) on failure.
+
#### slice_compute_data_size
+
```func
(int, int, int) slice_compute_data_size(slice s, int max_cells) impure asm "SDATASIZE";
```
+
A non-quiet version of `slice_compute_data_size?` that throws a cell overflow exception (8) on failure.
+
### Persistent storage save and load
+
#### get_data
+
```func
cell get_data() asm "c4 PUSH";
```
+
Returns the persistent contract storage cell. It can be parsed or modified with slice and builder primitives later.
+
#### set_data
+
```func
() set_data(cell c) impure asm "c4 POP";
```
+
Sets cell `c` as persistent contract data. You can update the persistent contract storage with this primitive.
+
### Continuation primitives
+
#### get_c3
+
```func
cont get_c3() impure asm "c3 PUSH";
```
+
Usually `c3` has a continuation initialized by the whole code of the contract. It is used for function calls. The primitive returns the current value of `c3`.
+
#### set_c3
+
```func
() set_c3(cont c) impure asm "c3 POP";
```
+
Updates the current value of `c3`. Usually, it is used for updating smart contract code in runtime. Note that after execution of this primitive, the current code (and the stack of recursive function calls) won't change, but any other function call will use a function from the new code.
+
#### bless
+
```func
cont bless(slice s) impure asm "BLESS";
```
+
Transforms `slice s` into a simple ordinary continuation `c` with `c.code = s`, and an empty stack, and savelist.
### Gas related primitives
+
#### accept_message
+
```func
() accept_message() impure asm "ACCEPT";
```
+
Sets the current gas limit `gl` to its maximum allowed value `gm` and resets the gas credit `gc` to zero, decreasing the value of `gr` by `gc` in the process. In other words, the current smart contract agrees to buy some gas to finish the current transaction. This action is required to process external messages that carry no value (hence no gas).
For more details check [accept_message effects](/develop/smart-contracts/guidelines/accept)
+
#### set_gas_limit
+
```func
() set_gas_limit(int limit) impure asm "SETGASLIMIT";
```
+
Sets the current gas limit `gl` to the minimum of `limit` and `gm`, and resets the gas credit `gc` to zero. At that point, if the amount of consumed gas (including the present instruction) exceeds the resulting value of `gl`, an (unhandled) out of gas exception is thrown before setting new gas limits. Notice that `set_gas_limit` with an argument `limit ≥ 2^63 − 1` is equivalent to `accept_message`.
For more details check [accept_message effects](/develop/smart-contracts/guidelines/accept)
+
#### commit
+
```func
() commit() impure asm "COMMIT";
```
+
Commits the current state of registers `c4` (“persistent data”) and `c5` (“actions”) so that the current execution is considered “successful” with the saved values even if an exception is thrown later.
+
#### buy_gas
+
```func
() buy_gas(int gram) impure asm "BUYGAS";
```
+
:::caution
`BUYGAS` opcode is currently not implemented
:::
@@ -309,100 +450,155 @@ Commits the current state of registers `c4` (“persistent data”) and `c5` (
Computes the amount of gas that can be bought for `gram` nanotoncoins and sets `gl` accordingly in the same way as `set_gas_limit`.
### Actions primitives
+
#### raw_reserve
+
```func
() raw_reserve(int amount, int mode) impure asm "RAWRESERVE";
```
+
Creates an output action which would reserve exactly `amount` nanotoncoins (if `mode = 0`), at most `amount` nanotoncoins (if `mode = 2`), or all but `amount` nanotoncoins (if `mode = 1` or `mode = 3`) from the remaining balance of the account. It is roughly equivalent to creating an outbound message carrying `amount` nanotoncoins (or `b − amount` nanotoncoins, where `b` is the remaining balance) to oneself, so that the subsequent output actions would not be able to spend more money than the remainder. Bit +2 in `mode` means that the external action does not fail if the specified amount cannot be reserved; instead, all the remaining balance is reserved. Bit +8 in `mode` means `amount <- -amount` before performing any further actions. Bit +4 in `mode` means that `amount` is increased by the original balance of the current account (before the compute phase), including all extra currencies before performing any other checks and actions. Currently, `amount` must be a non-negative integer, and `mode` must be in the range `0..15`.
+
#### raw_reserve_extra
+
```func
() raw_reserve_extra(int amount, cell extra_amount, int mode) impure asm "RAWRESERVEX";
```
+
Similar to `raw_reserve` but also accepts a dictionary `extra_amount` (represented by `cell` or `null`) with extra currencies. In this way, currencies other than Toncoin can be reserved.
+
#### send_raw_message
+
```func
() send_raw_message(cell msg, int mode) impure asm "SENDRAWMSG";
```
+
Sends a raw message contained in `msg`, which should contain a correctly serialized object Message X, with the only exception that the source address is allowed to have a dummy value `addr_none` (to be automatically replaced with the current smart contract address), and `ihr_fee`, `fwd_fee`, `created_lt` and `created_at` fields can have arbitrary values (to be rewritten with correct values during the action phase of the current transaction). The integer parameter `mode` contains the flags.
-There are currently 3 Modes and 3 Flags for messages. You can combine a single mode with several (maybe none) flags to get a required `mode`. Combination simply means getting sum of their values. A table with descriptions of Modes and Flags is given below.
+There are currently 3 Modes and 4 Flags for messages. You can combine a single mode with several (maybe none) flags to get a required `mode`. Combination simply means getting sum of their values. A table with descriptions of Modes and Flags is given below.
-| Mode | Description |
-|:-|:-|
-| `0` | Ordinary message |
-| `64` | Carry all the remaining value of the inbound message in addition to the value initially indicated in the new message |
+| Mode | Description |
+| :---- | :--------------------------------------------------------------------------------------------------------------------- |
+| `0` | Ordinary message |
+| `64` | Carry all the remaining value of the inbound message in addition to the value initially indicated in the new message |
| `128` | Carry all the remaining balance of the current smart contract instead of the value originally indicated in the message |
-| Flag | Description |
-|:-|:-|
-| `+1` | Pay transfer fees separately from the message value |
-| `+2` | Ignore any errors arising while processing this message during the action phase |
-| `+32` | Current account must be destroyed if its resulting balance is zero (often used with Mode 128) |
+| Flag | Description |
+| :---- | :---------------------------------------------------------------------------------------------------------------- |
+| `+1` | Pay transfer fees separately from the message value |
+| `+2` | Ignore some errors arising while processing this message during the action phase (check note below) |
+| `+16` | In the case of action fail - bounce transaction. No effect if `+2` is used. |
+| `+32` | Current account must be destroyed if its resulting balance is zero (often used with Mode 128) |
+
+:::info +2 flag
+Note that `+2` flag ignore only following errors arising while processing message during the action phase:
+1. Not enough Toncoins:
+ - Not enough value to transfer with the message (all of the inbound message value has been consumed).
+ - Not enough funds to process a message.
+ - Not enough value attached to the message to pay forwarding fees.
+ - Not enough extra currency to send with the message.
+ - Not enough funds to pay for an outbound external message.
+2. Message is too large (check [Message size](/develop/smart-contracts/messages#message-size) for more).
+3. The message has too big Merkle depth.
+
+However, it does not ignore errors in the following scenarios:
+1. The message has an invalid format.
+2. The message mode includes both 64 and 128 mods.
+3. The outbound message has invalid libraries in StateInit.
+4. The external message is not ordinary or includes +16 or +32 flag or both.
+:::
-For example, if you want to send a regular message and pay transfer fees separately, use the Mode `0` and Flag `+1` to get `mode = 1`. If you want to send the whole contract balance and destroy it immidiately, use the Mode `128` and Flag `+32` to get `mode = 160`.
+:::warning
+1. **+16 flag** - do not use in external messages (e.g. to wallets), because there is no sender to receive the bounced message.
+2. **+2 flag** - important in external messages (e.g. to wallets).
+:::
+
+You can see a detailed example [here](/develop/smart-contracts/messages#example-with-use-cases).
#### set_code
+
```func
() set_code(cell new_code) impure asm "SETCODE";
```
+
Creates an output action that would change this smart contract code to that given by cell `new_code`. Notice that this change will take effect only after the successful termination of the current run of the smart contract. (Cf. [set_c3](/develop/func/stdlib#set_c3.))
### Random number generator primitives
+
The pseudo-random number generator uses the random seed, an unsigned 256-bit Integer, and (sometimes) other data kept in [c7](/learn/tvm-instructions/tvm-overview#control-registers). The initial value of the random seed before a smart contract is executed in TON Blockchain is a hash of the smart contract address and the global block random seed. If there are several runs of the same smart contract inside a block, then all of these runs will have the same random seed. This can be fixed, for example, by running `randomize_lt` before using the pseudo-random number generator for the first time.
:::caution
Keep in mind that random numbers generated by the functions below can be predicted if you do not use additional tricks.
- - [Random number generation](/develop/smart-contracts/guidelines/random-number-generation)
+
+- [Random number generation](/develop/smart-contracts/guidelines/random-number-generation)
+
:::
+
#### random
+
```func
int random() impure asm "RANDU256";
```
+
Generates a new pseudo-random unsigned 256-bit integer `x`. The algorithm is as follows: if `r` is the old value of the random seed considered a 32-byte array (by constructing the big-endian representation of an unsigned 256-bit integer), then its `sha512(r)` is computed; the first 32 bytes of this hash are stored as the new value `r'` of the random seed, and the remaining 32 bytes are returned as the next random value `x`.
+
#### rand
+
```func
int rand(int range) impure asm "RAND";
```
+
Generates a new pseudo-random integer `z` in the range `0..range−1` (or `range..−1` if `range < 0`). More precisely, an unsigned random value `x` is generated as in `random`; then `z := x * range / 2^256` is
computed.
#### get_seed
+
```func
int get_seed() impure asm "RANDSEED";
```
+
Returns the current random seed as an unsigned 256-bit integer.
+
#### set_seed
+
```func
int set_seed(int seed) impure asm "SETRAND";
```
+
Sets a random seed to an unsigned 256-bit `seed`.
#### randomize
+
```func
() randomize(int x) impure asm "ADDRAND";
```
+
Mixes an unsigned 256-bit integer `x` into a random seed `r` by setting the random seed to sha256 of the concatenation of two 32-byte strings: the first with a big-endian representation of the old seed `r`, and the second with a big-endian representation of `x`.
#### randomize_lt
+
```func
() randomize_lt() impure asm "LTIME" "ADDRAND";
```
+
Equivalent to `randomize(cur_lt());`.
### Address manipulation primitives
+
The address manipulation primitives listed below serialize and deserialize values according to the following TL-B scheme.
+
```func
addr_none$00 = MsgAddressExt;
addr_extern$01 len:(## 8) external_address:(bits len)
= MsgAddressExt;
-
+
anycast_info$_ depth:(#<= 30) { depth >= 1 }
rewrite_pfx:(bits depth) = Anycast;
-
+
addr_std$10 anycast:(Maybe Anycast)
workchain_id:int8 address:bits256 = MsgAddressInt;
-
+
addr_var$11 anycast:(Maybe Anycast) addr_len:(## 9)
workchain_id:int32 address:(bits addr_len) = MsgAddressInt;
_ _:MsgAddressInt = MsgAddress;
@@ -412,55 +608,90 @@ int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool
src:MsgAddress dest:MsgAddressInt
value:CurrencyCollection ihr_fee:Grams fwd_fee:Grams
created_lt:uint64 created_at:uint32 = CommonMsgInfoRelaxed;
-
+
ext_out_msg_info$11 src:MsgAddress dest:MsgAddressExt
created_lt:uint64 created_at:uint32 = CommonMsgInfoRelaxed;
```
+
A deserialized `MsgAddress` is represented by the tuple `t` as follows:
-* `addr_none` is represented by `t = (0)`, i.e., a tuple containing exactly
-one integer that equals zero
-* `addr_extern` is represented by `t = (1, s)`, where slice `s` contains the
-field `external_address`. In other words, `t` is a pair (a tuple consisting of two entries), containing an integer equal to one and slice `s`
-* `addr_std` is represented by `t = (2, u, x, s)`, where `u` is either `null` (if `anycast` is absent) or a slice `s'` containing `rewrite_pfx` (if `anycast` is present). Next, integer `x` is the `workchain_id`, and slice `s` contains the address
-* `addr_var` is represented by `t = (3, u, x, s)`, where `u`, `x`, and `s` have the same meaning as for `addr_std`
+
+- `addr_none` is represented by `t = (0)`, i.e., a tuple containing exactly
+ one integer that equals zero
+- `addr_extern` is represented by `t = (1, s)`, where slice `s` contains the
+ field `external_address`. In other words, `t` is a pair (a tuple consisting of two entries), containing an integer equal to one and slice `s`
+- `addr_std` is represented by `t = (2, u, x, s)`, where `u` is either `null` (if `anycast` is absent) or a slice `s'` containing `rewrite_pfx` (if `anycast` is present). Next, integer `x` is the `workchain_id`, and slice `s` contains the address
+- `addr_var` is represented by `t = (3, u, x, s)`, where `u`, `x`, and `s` have the same meaning as for `addr_std`
#### load_msg_addr
+
```func
(slice, slice) load_msg_addr(slice s) asm( -> 1 0) "LDMSGADDR";
```
+
Loads from `slice s` the only prefix that is a valid `MsgAddress` and returns both this prefix `s'` and the remainder `s''` of `s` as slices.
+
#### parse_addr
+
```func
tuple parse_addr(slice s) asm "PARSEMSGADDR";
```
+
Decomposes `slice s` containing a valid `MsgAddress` into `tuple t` with separate fields of this `MsgAddress`. If `s` is not a valid `MsgAddress`, a cell deserialization exception is thrown.
#### parse_std_addr
+
```func
(int, int) parse_std_addr(slice s) asm "REWRITESTDADDR";
```
+
Parses slice `s` containing a valid `MsgAddressInt` (usually `msg_addr_std`), applies rewriting from the `anycast` (if present) to the same-length prefix of the address, and returns both the workchain and the 256-bit address as integers. If the address is not 256-bit or if `s` is not a valid serialization of `MsgAddressInt`, throws a cell `deserialization` exception.
+
#### parse_var_addr
+
```func
(int, slice) parse_var_addr(slice s) asm "REWRITEVARADDR";
```
+
A variant of `parse_std_addr` that returns the (rewritten) address as a slice `s`, even if it is not exactly 256 bit long (represented by `msg_addr_var`).
## Debug primitives
-Currently, only one function is available.
+
+Debug primitives can be used for inspecting state of various variables while running tests or console scripts.
+
+#### ~dump
+
+```func
+forall X -> () ~dump(X value) impure asm "s0 DUMP";
+```
+
+Outputs a value. Several values can be dumped as a tuple, e.g. `~dump([v1, v2, v3])`.
+
+#### ~strdump
+
+```func
+() ~strdump(slice str) impure asm "STRDUMP";
+```
+
+Dumps a string. Slice parameter bit length must be divisible by 8.
+
#### dump_stack
+
```func
() dump_stack() impure asm "DUMPSTK";
```
+
Dumps the stack (at most the top 255 values) and shows the total stack depth.
## Slice primitives
-It is said that a primitive *loads* some data if it returns the data and the remainder of the slice (so it can also be used as a [modifying method](/develop/func/statements#modifying-methods)).
-It is said that a primitive *preloads* some data if it returns only the data (it can be used as a [non-modifying method](/develop/func/statements#non-modifying-methods)).
+It is said that a primitive _loads_ some data if it returns the data and the remainder of the slice (so it can also be used as a [modifying method](/develop/func/statements#modifying-methods)).
+
+It is said that a primitive _preloads_ some data if it returns only the data (it can be used as a [non-modifying method](/develop/func/statements#non-modifying-methods)).
Unless otherwise stated, loading and preloading primitives read data from a prefix of the slice.
+
#### begin_parse
+
```func
slice begin_parse(cell c) asm "CTOS";
```
@@ -468,212 +699,329 @@ slice begin_parse(cell c) asm "CTOS";
Converts `cell` into `slice`. Notice that `c` must be either an ordinary cell or an exotic cell (see [TVM.pdf](https://ton.org/tvm.pdf), 3.1.2) which is automatically loaded to yield an ordinary cell `c'`converted into `slice` afterwards.
#### end_parse
+
```func
() end_parse(slice s) impure asm "ENDS";
```
+
Checks if `s` is empty. If not, throws an exception.
+
#### load_ref
+
```func
(slice, cell) load_ref(slice s) asm( -> 1 0) "LDREF";
```
+
Loads the first reference from a slice.
+
#### preload_ref
+
```func
cell preload_ref(slice s) asm "PLDREF";
```
+
Preloads the first reference from a slice.
+
#### load_int
+
```func
;; (slice, int) ~load_int(slice s, int len) asm(s len -> 1 0) "LDIX";
```
+
Loads a signed `len`-bit integer from a slice.
+
#### load_uint
+
```func
;; (slice, int) ~load_uint(slice s, int len) asm( -> 1 0) "LDUX";
```
+
Loads an unsigned `len`-bit integer from a slice.
+
#### preload_int
+
```func
;; int preload_int(slice s, int len) asm "PLDIX";
```
+
Preloads a signed `len`-bit integer from a slice.
+
#### preload_uint
+
```func
;; int preload_uint(slice s, int len) asm "PLDUX";
```
+
Preloads an unsigned `len`-bit integer from a slice.
+
#### load_bits
+
```func
;; (slice, slice) load_bits(slice s, int len) asm(s len -> 1 0) "LDSLICEX";
```
+
Loads the first `0 ≤ len ≤ 1023` bits from slice `s` into a separate slice `s''`.
#### preload_bits
+
```func
;; slice preload_bits(slice s, int len) asm "PLDSLICEX";
```
+
Preloads the first `0 ≤ len ≤ 1023` bits from slice `s` into a separate slice `s''`.
#### load_coins
+
```func
(slice, int) load_coins(slice s) asm( -> 1 0) "LDGRAMS";
```
+
Loads serialized amount of Toncoins (any unsigned integer up to `2^120 - 1`).
#### skip_bits
+
```func
slice skip_bits(slice s, int len) asm "SDSKIPFIRST";
(slice, ()) ~skip_bits(slice s, int len) asm "SDSKIPFIRST";
```
+
Returns all but the first `0 ≤ len ≤ 1023` bits of `s`.
+
#### first_bits
+
```func
slice first_bits(slice s, int len) asm "SDCUTFIRST";
```
+
Returns the first `0 ≤ len ≤ 1023` bits of `s`.
+
#### skip_last_bits
+
```func
slice skip_last_bits(slice s, int len) asm "SDSKIPLAST";
(slice, ()) ~skip_last_bits(slice s, int len) asm "SDSKIPLAST";
```
+
Returns all but the last `0 ≤ len ≤ 1023` bits of `s`.
+
#### slice_last
+
```func
slice slice_last(slice s, int len) asm "SDCUTLAST";
```
+
Returns the last `0 ≤ len ≤ 1023` bits of `s`.
+
#### load_dict
+
```func
(slice, cell) load_dict(slice s) asm( -> 1 0) "LDDICT";
```
+
Loads a dictionary `D` from slice `s`. May be applied to dictionaries or to values of arbitrary `Maybe ^Y` types (returns `null` if `nothing` constructor is used).
+
#### preload_dict
+
```func
cell preload_dict(slice s) asm "PLDDICT";
```
+
Preloads a dictionary `D` from slice `s`.
+
#### skip_dict
+
```func
slice skip_dict(slice s) asm "SKIPDICT";
```
+
Loads a dictionary as `load_dict` but returns only the remainder of the slice.
+
### Slice size primitives
+
#### slice_refs
+
```func
int slice_refs(slice s) asm "SREFS";
```
+
Returns the number of references in slice `s`.
+
#### slice_bits
+
```func
int slice_bits(slice s) asm "SBITS";
```
+
Returns the number of data bits in slice `s`.
+
#### slice_bits_refs
+
```func
(int, int) slice_bits_refs(slice s) asm "SBITREFS";
```
+
Returns both the number of data bits and the number of references in `s`.
+
#### slice_empty?
+
```func
int slice_empty?(slice s) asm "SEMPTY";
```
+
Checks whether slice `s` is empty (i.e., contains no bits of data and no cell references).
+
#### slice_data_empty?
+
```func
int slice_data_empty?(slice s) asm "SDEMPTY";
```
+
Checks whether slice `s` has no bits of data.
+
#### slice_refs_empty?
+
```func
int slice_refs_empty?(slice s) asm "SREMPTY";
```
+
Checks whether slice `s` has no references.
+
#### slice_depth
+
```func
int slice_depth(slice s) asm "SDEPTH";
```
+
Returns the depth of slice `s`. If `s` has no references, then returns `0`; otherwise, the returned value is one plus the maximum of depths of cells referred to from `s`.
## Builder primitives
-It is said that a primitive *stores* a value `x` into a builder `b` if it returns a modified version of the builder `b'` with the value `x` stored at the end of it. It can be used as a [non-modifying method](/develop/func/statements#non-modifying-methods).
+
+It is said that a primitive _stores_ a value `x` into a builder `b` if it returns a modified version of the builder `b'` with the value `x` stored at the end of it. It can be used as a [non-modifying method](/develop/func/statements#non-modifying-methods).
All of the primitives listed below verify whether there is enough space in the `builder`first, and then the range of the value being serialized.
+
#### begin_cell
+
```func
builder begin_cell() asm "NEWC";
```
+
Creates a new empty `builder`.
+
#### end_cell
+
```func
cell end_cell(builder b) asm "ENDC";
```
+
Converts `builder` into an ordinary `cell`.
+
#### store_ref
+
```func
builder store_ref(builder b, cell c) asm(c b) "STREF";
```
+
Stores a reference to cell `c` into builder `b`.
+
#### store_uint
+
```func
builder store_uint(builder b, int x, int len) asm(x b len) "STUX";
```
+
Stores an unsigned `len`-bit integer `x` into `b` for `0 ≤ len ≤ 256`.
+
#### store_int
+
```func
builder store_int(builder b, int x, int len) asm(x b len) "STIX";
```
+
Stores a signed `len`-bit integer `x` into `b` for `0 ≤ len ≤ 257`.
+
#### store_slice
+
```func
builder store_slice(builder b, slice s) asm "STSLICER";
```
+
Stores slice `s` into builder `b`.
+
#### store_grams
+
```func
builder store_grams(builder b, int x) asm "STGRAMS";
```
+
+#### store_coins
+
+```func
+builder store_coins(builder b, int x) asm "STGRAMS";
+```
+
Stores (serializes) an integer `x` in the range `0..2^120 − 1` into builder `b`. The serialization of `x` consists of a 4-bit unsigned big-endian integer `l`, which is the smallest integer `l ≥ 0`, such that `x < 2^8l`, followed by an `8l`-bit unsigned big-endian representation of `x`. If `x` does not belong to the supported range, a range check exception is thrown.
It is the most common way of storing Toncoins.
#### store_dict
+
```func
builder store_dict(builder b, cell c) asm(c b) "STDICT";
```
+
Stores dictionary `D` represented by cell `c` or `null` into builder `b`. In other words, stores `1`-bit and a reference to `c` if `c` is not `null` and `0`-bit otherwise.
+
#### store_maybe_ref
+
```func
builder store_maybe_ref(builder b, cell c) asm(c b) "STOPTREF";
```
+
Equivalent to `store_dict`.
### Builder size primitives
+
#### builder_refs
+
```func
int builder_refs(builder b) asm "BREFS";
```
+
Returns the number of cell references already stored in builder `b`.
+
#### builder_bits
+
```func
int builder_bits(builder b) asm "BBITS";
```
+
Returns the number of data bits already stored in builder `b`.
+
#### builder_depth
+
```func
int builder_depth(builder b) asm "BDEPTH";
```
+
Returns the depth of builder `b`. If no cell references are stored in `b`, then returns `0`; otherwise, the returned value is one plus the maximum of depths of cells referred to from `b`.
## Cell primitives
+
#### cell_depth
+
```func
int cell_depth(cell c) asm "CDEPTH";
```
+
Returns the depth of cell `c`. If `c` has no references, then return `0`; otherwise, the returned value is one plus the maximum of depths of cells referred to from `c`. If `c` is a `null` instead of a cell, it returns zero.
+
#### cell_null?
+
```func
int cell_null?(cell c) asm "ISNULL";
```
+
Checks whether `c` is a `null`. Usually a `null`-cell represents an empty dictionary. FunC also has polymorphic `null?` built-in. (See [built-ins](/develop/func/builtins#other-primitives).)
## Dictionaries primitives
@@ -683,15 +1031,18 @@ The dictionary primitives below are low-level and do not check that the structur
:::
As said in [TVM.pdf](https://ton.org/tvm.pdf):
+
> Dictionaries admit two different representations as TVM stack values:
-> * A slice `s` with a serialization of a TL-B value of type `HashmapE(n, X)`. In other words, `s` consists either of one bit equal to zero (if the dictionary is empty) or of one bit equal to one and a reference to a cell containing the root of the binary tree, i.e., a serialized value of type `Hashmap(n, X)`.
-> * A “Maybe cell” `c^?`, i.e., a value that is either a cell (containing a serialized value of type `Hashmap(n, X)` as before) or a `null` (corresponding to an empty dictionary, cf. [null values](/develop/func/types#null-values)). When a “Maybe cell” `c^?` is used to represent a dictionary, we usually denote it by `D`.
+>
+> - A slice `s` with a serialization of a TL-B value of type `HashmapE(n, X)`. In other words, `s` consists either of one bit equal to zero (if the dictionary is empty) or of one bit equal to one and a reference to a cell containing the root of the binary tree, i.e., a serialized value of type `Hashmap(n, X)`.
+> - A “Maybe cell” `c^?`, i.e., a value that is either a cell (containing a serialized value of type `Hashmap(n, X)` as before) or a `null` (corresponding to an empty dictionary, cf. [null values](/develop/func/types#null-values)). When a “Maybe cell” `c^?` is used to represent a dictionary, we usually denote it by `D`.
>
> Most of the dictionary primitives listed below accept and return dictionaries in the second form, which is more convenient for stack manipulation. However, serialized dictionaries inside larger TL-B objects use the first representation.
In FunC dictionaries are also represented by the `cell` type with the implicit assumption that it may be a `null` value. There are no separate types for dictionaries with different key lengths or value types (after all, it's FunC, not FunC++).
### Taxonomy note
+
A dictionary primitive may interpret the keys of the dictionary either as unsigned `l`-bit integers, as signed `l`-bit integers, or as `l`-bit slices. The primitives listed below differ by the prefix before the word `dict` in their names. `i` stands for signed integer keys, `u` stands for unsigned integer keys, and an empty prefix stands for slice keys.
For example, `udict_set` is a set-by-key function for dictionaries with unsigned integer keys; `idict_set` is the corresponding function for dictionaries with signed integer keys; `dict_set` is the function for dictionaries with slice keys.
@@ -701,9 +1052,11 @@ An empty prefix is used in the titles.
Also, some of the primitives have their counterparts prefixed with `~`. It makes it possible to use them as [modifying methods](/develop/func/statements#modifying-methods).
### Dictionary's values
-A value in a dictionary may be stored either directly as a subslice of an inner dictionary cell or as a reference to a separate cell. In the first case, it is not guaranteed that if the value fits into a cell, it fits into the dictionary (because a part of the inner cell may already be occupied by a part of the corresponding key). On the other hand, the second storing way is less gas-efficient. The second way is equivalent to storing in the first way a slice with empty data bits and exactly one reference to the value.
+
+Values within a dictionary can be stored either as a subslice within an inner dictionary cell or through a reference to a separate cell. In the former scenario, it is not assured that a value small enough to fit within a cell will also fit within the dictionary, as part of the inner cell's space may already be occupied by a portion of the corresponding key. Conversely, the latter method of storage is less efficient in terms of gas usage. Storing a value using the second method is tantamount to inserting a slice with no data bits and a single reference to the value in the first method.
#### dict_set
+
```func
cell udict_set(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTUSET";
cell idict_set(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTISET";
@@ -712,68 +1065,99 @@ cell dict_set(cell dict, int key_len, slice index, slice value) asm(value index
(cell, ()) ~idict_set(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTISET";
(cell, ()) ~dict_set(cell dict, int key_len, slice index, slice value) asm(value index dict key_len) "DICTSET";
```
+
Sets the value associated with `key_len`-bit key `index` in dictionary `dict` to `value` (a slice) and returns the resulting dictionary.
+
#### dict_set_ref
+
```func
cell idict_set_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTISETREF";
cell udict_set_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTUSETREF";
(cell, ()) ~idict_set_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTISETREF";
(cell, ()) ~udict_set_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTUSETREF";
```
+
Similar to `dict_set` but with the value set to a reference to cell `value`.
+
#### dict_get?
+
```func
(slice, int) idict_get?(cell dict, int key_len, int index) asm(index dict key_len) "DICTIGET" "NULLSWAPIFNOT";
(slice, int) udict_get?(cell dict, int key_len, int index) asm(index dict key_len) "DICTUGET" "NULLSWAPIFNOT";
```
-Looks up key `index` in dictionary `dict` with `key_len`-bit keys. On success, returns the value found as a slice along with a `-1` flag indicating success. If fails, it returns `(null, 0)`.
+
+Searches for the key `index` within the `dict` dictionary, which uses keys of `key_len` bits. If successful, it retrieves the associated value as a `slice` and returns a flag value of `-1` to indicate **success**. If the search fails, it returns `(null, 0)`.
+
#### dict_get_ref?
+
```func
(cell, int) idict_get_ref?(cell dict, int key_len, int index) asm(index dict key_len) "DICTIGETREF";
(cell, int) udict_get_ref?(cell dict, int key_len, int index) asm(index dict key_len) "DICTUGETREF";
```
+
Similar to `dict_get?` but returns the first reference of the found value.
+
#### dict_get_ref
+
```func
cell idict_get_ref(cell dict, int key_len, int index) asm(index dict key_len) "DICTIGETOPTREF";
```
+
A variant of `dict_get_ref?` that returns `null` instead of the value if the key `index` is absent from the dictionary `dict`.
#### dict_set_get_ref
+
```func
(cell, cell) idict_set_get_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTISETGETOPTREF";
(cell, cell) udict_set_get_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTUSETGETOPTREF";
```
+
Sets the value associated with `index` to `value` (if `value` is `null`, then the key is deleted instead) and returns the old value (or `null` if the value was absent).
+
#### dict_delete?
+
```func
(cell, int) idict_delete?(cell dict, int key_len, int index) asm(index dict key_len) "DICTIDEL";
(cell, int) udict_delete?(cell dict, int key_len, int index) asm(index dict key_len) "DICTUDEL";
```
+
Deletes `key_len`-bit key `index` from the dictionary `dict`. If the key is present, returns the modified dictionary `dict'` and the success flag `−1`. Otherwise, returns the original dictionary `dict` and `0`.
+
#### dict_delete_get?
+
```func
(cell, slice, int) idict_delete_get?(cell dict, int key_len, int index) asm(index dict key_len) "DICTIDELGET" "NULLSWAPIFNOT";
(cell, slice, int) udict_delete_get?(cell dict, int key_len, int index) asm(index dict key_len) "DICTUDELGET" "NULLSWAPIFNOT";
(cell, (slice, int)) ~idict_delete_get?(cell dict, int key_len, int index) asm(index dict key_len) "DICTIDELGET" "NULLSWAPIFNOT";
(cell, (slice, int)) ~udict_delete_get?(cell dict, int key_len, int index) asm(index dict key_len) "DICTUDELGET" "NULLSWAPIFNOT";
```
+
Deletes `key_len`-bit key `index` from dictionary `dict`. If the key is present, returns the modified dictionary `dict'`, the original value `x` associated with the key k (represented by a Slice), and the success flag `−1`. Otherwise, returns `(dict, null, 0)`.
+
#### dict_add?
+
```func
(cell, int) udict_add?(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTUADD";
(cell, int) idict_add?(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTIADD";
```
+
An `add` counterpart of `dict_set` sets the value associated with key `index` in dictionary `dict` to `value` but only if it is not already present in `D`. Returns either modified version of the dictionary and `-1` flag or `(dict, 0)`.
+
#### dict_replace?
+
```func
(cell, int) udict_replace?(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTUREPLACE";
(cell, int) idict_replace?(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTIREPLACE";
```
+
A `replace` operation similar to `dict_set` but which sets the value of key `index` in dictionary `dict` to `value` only if the key was already present in `dict`. Returns either modified version of the dictionary and `-1` flag or `(dict, 0)`.
+
### Builder counterparts
+
The following primitives accept the new value as a builder instead of a slice, which often is more convenient if the value needs to be serialized from several components computed in the stack. The net effect is roughly equivalent to converting b into a slice and executing the corresponding primitive listed above.
+
#### dict_set_builder
+
```func
cell udict_set_builder(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTUSETB";
cell idict_set_builder(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTISETB";
@@ -782,20 +1166,29 @@ cell dict_set_builder(cell dict, int key_len, slice index, builder value) asm(va
(cell, ()) ~udict_set_builder(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTUSETB";
(cell, ()) ~dict_set_builder(cell dict, int key_len, slice index, builder value) asm(value index dict key_len) "DICTSETB";
```
+
Similar to `dict_set` but accepts a builder.
+
#### dict_add_builder?
+
```func
(cell, int) udict_add_builder?(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTUADDB";
(cell, int) idict_add_builder?(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTIADDB";
```
+
Similar to `dict_add?` but accepts a builder.
+
#### dict_replace_builder?
+
```func
(cell, int) udict_replace_builder?(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTUREPLACEB";
(cell, int) idict_replace_builder?(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTIREPLACEB";
```
+
Similar to `dict_replace?` but accepts a builder.
+
#### dict_delete_get_min
+
```func
(cell, int, slice, int) udict_delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) "DICTUREMMIN" "NULLSWAPIFNOT2";
(cell, int, slice, int) idict_delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) "DICTIREMMIN" "NULLSWAPIFNOT2";
@@ -804,11 +1197,13 @@ Similar to `dict_replace?` but accepts a builder.
(cell, (int, slice, int)) ~udict::delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) "DICTUREMMIN" "NULLSWAPIFNOT2";
(cell, (slice, slice, int)) ~dict::delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) "DICTREMMIN" "NULLSWAPIFNOT2";
```
+
Computes the minimum key `k` in dictionary `dict`, removes it, and returns `(dict', k, x, -1)`, where `dict'` is the modified version of `dict` and `x` is the value associated with `k`. If the dict is empty, returns `(dict, null, null, 0)`.
Note that the key returned by `idict_delete_get_min` may differ from the key returned by `dict_delete_get_min` and `udict_delete_get_min`.
#### dict_delete_get_max
+
```func
(cell, int, slice, int) udict_delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) "DICTUREMMAX" "NULLSWAPIFNOT2";
(cell, int, slice, int) idict_delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) "DICTIREMMAX" "NULLSWAPIFNOT2";
@@ -817,118 +1212,174 @@ Note that the key returned by `idict_delete_get_min` may differ from the key ret
(cell, (int, slice, int)) ~idict::delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) "DICTIREMMAX" "NULLSWAPIFNOT2";
(cell, (slice, slice, int)) ~dict::delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) "DICTREMMAX" "NULLSWAPIFNOT2";
```
+
Computes the maximum key `k` in dictionary `dict`, removes it, and returns `(dict', k, x, -1)`, where `dict'` is the modified version of `dict` and `x` is the value associated with `k`. If the dict is empty, returns `(dict, null, null, 0)`.
#### dict_get_min?
+
```func
(int, slice, int) udict_get_min?(cell dict, int key_len) asm (-> 1 0 2) "DICTUMIN" "NULLSWAPIFNOT2";
(int, slice, int) idict_get_min?(cell dict, int key_len) asm (-> 1 0 2) "DICTIMIN" "NULLSWAPIFNOT2";
```
+
Computes the minimum key `k` in dictionary `dict`, the associated value `x`, and returns `(k, x, -1)`. If the dictionary is empty, returns `(null, null, 0)`.
+
#### dict_get_max?
+
```func
(int, slice, int) udict_get_max?(cell dict, int key_len) asm (-> 1 0 2) "DICTUMAX" "NULLSWAPIFNOT2";
(int, slice, int) idict_get_max?(cell dict, int key_len) asm (-> 1 0 2) "DICTIMAX" "NULLSWAPIFNOT2";
```
+
Computes the maximum key `k` in dictionary `dict`, the associated value `x`, and returns `(k, x, -1)`. If the dictionary is empty, returns `(null, null, 0)`.
+
#### dict_get_min_ref?
+
```func
(int, cell, int) udict_get_min_ref?(cell dict, int key_len) asm (-> 1 0 2) "DICTUMINREF" "NULLSWAPIFNOT2";
(int, cell, int) idict_get_min_ref?(cell dict, int key_len) asm (-> 1 0 2) "DICTIMINREF" "NULLSWAPIFNOT2";
```
+
Similar to `dict_get_min?` but returns the only reference in the value as a reference.
+
#### dict_get_max_ref?
+
```func
(int, cell, int) udict_get_max_ref?(cell dict, int key_len) asm (-> 1 0 2) "DICTUMAXREF" "NULLSWAPIFNOT2";
(int, cell, int) idict_get_max_ref?(cell dict, int key_len) asm (-> 1 0 2) "DICTIMAXREF" "NULLSWAPIFNOT2";
```
+
Similar to `dict_get_max?` but returns the only reference in the value as a reference.
+
#### dict_get_next?
+
```func
(int, slice, int) udict_get_next?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTUGETNEXT" "NULLSWAPIFNOT2";
(int, slice, int) idict_get_next?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTIGETNEXT" "NULLSWAPIFNOT2";
```
+
Computes the minimum key `k` in dictionary `dict` that is greater than `pivot`; returns `k`, associated value, and a flag indicating success. If the dictionary is empty, returns `(null, null, 0)`.
+
#### dict_get_nexteq?
+
```func
(int, slice, int) udict_get_nexteq?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTUGETNEXTEQ" "NULLSWAPIFNOT2";
(int, slice, int) idict_get_nexteq?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTIGETNEXTEQ" "NULLSWAPIFNOT2";
```
+
Similar to `dict_get_next?` but computes the minimum key `k` that is greater than or equal to `pivot`.
+
#### dict_get_prev?
+
```func
(int, slice, int) udict_get_prev?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTUGETPREV" "NULLSWAPIFNOT2";
(int, slice, int) idict_get_prev?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTIGETPREV" "NULLSWAPIFNOT2";
```
+
Similar to `dict_get_next?` but computes the maximum key `k` smaller than `pivot`.
+
#### dict_get_preveq?
+
```func
(int, slice, int) udict_get_preveq?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTUGETPREVEQ" "NULLSWAPIFNOT2";
(int, slice, int) idict_get_preveq?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTIGETPREVEQ" "NULLSWAPIFNOT2";
```
+
Similar to `dict_get_prev?` but computes the maximum key `k` smaller than or equal to `pivot`.
+
#### new_dict
+
```func
cell new_dict() asm "NEWDICT";
```
+
Creates an empty dictionary, which is actually a `null` value. Special case of `null()`.
+
#### dict_empty?
+
```func
int dict_empty?(cell c) asm "DICTEMPTY";
```
+
Checks whether a dictionary is empty. Equivalent to `cell_null?`.
## Prefix dictionaries primitives
-TVM also supports dictionaries with non-fixed length keys which form a prefix code (i.e., there is no key that is a prefix to another key). Learn more about them in [TVM.pdf](https://ton.org/tvm.pdf).
+
+TVM also supports dictionaries with non-fixed length keys which form a prefix code (i.e., there is no key that is a prefix to another key). Learn more about them in the [TVM Instruction](/learn/tvm-instructions/tvm-overview) section.
#### pfxdict_get?
+
```func
(slice, slice, slice, int) pfxdict_get?(cell dict, int key_len, slice key) asm(key dict key_len) "PFXDICTGETQ" "NULLSWAPIFNOT2";
```
+
Returns `(s', x, s'', -1)` or `(null, null, s, 0)`.
Looks up the unique prefix of slice `key` present in the prefix code dictionary `dict`. If found, the prefix of `s` is returned as `s'` and the corresponding value (also a slice) as `x`. The remainder of `s` is returned as slice `s''`. If no prefix of `s` is key in prefix code dictionary `dict`, it returns the unchanged `s` and a zero flag to indicate failure.
+
#### pfxdict_set?
+
```func
(cell, int) pfxdict_set?(cell dict, int key_len, slice key, slice value) asm(value key dict key_len) "PFXDICTSET";
```
+
Similar to `dict_set` but may fail if the key is a prefix of another key presented in the dictionary. Indicating success, returns a flag.
+
#### pfxdict_delete?
+
```func
(cell, int) pfxdict_delete?(cell dict, int key_len, slice key) asm(key dict key_len) "PFXDICTDEL";
```
+
Similar to `dict_delete?`.
## Special primitives
+
#### null
+
```func
forall X -> X null() asm "PUSHNULL";
```
+
By the TVM type `Null`, FunC represents the absence of a value of some atomic type. So `null` can actually have any atomic type.
+
#### ~impure_touch
+
```func
forall X -> (X, ()) ~impure_touch(X x) impure asm "NOP";
```
-Mark a variable as used, such that the code which produced it won't be deleted even if it is not impure. (c.f. [impure specifier](/develop/func/functions#impure-specifier))
+Mark a variable as used, such that the code which produced it won't be deleted even if it is not impure. (c.f. [impure specifier](/develop/func/functions#impure-specifier))
## Other primitives
+
#### min
+
```func
int min(int x, int y) asm "MIN";
```
+
Computes the minimum of two integers `x` and `y`.
+
#### max
+
```func
int max(int x, int y) asm "MAX";
```
+
Computes the maximum of two integers `x` and `y`.
+
#### minmax
+
```func
(int, int) minmax(int x, int y) asm "MINMAX";
```
+
Sorts two integers.
+
#### abs
+
```func
int abs(int x) asm "ABS";
```
+
Computes the absolute value of the integer `x`.
diff --git a/docs/develop/func/types.md b/docs/develop/func/types.md
index 510060ef1f..10a10e578a 100644
--- a/docs/develop/func/types.md
+++ b/docs/develop/func/types.md
@@ -1,6 +1,14 @@
# Types
+
+:::info
+
+FunC documentation was initially written by [@akifoq](https://github.com/akifoq).
+
+:::
+
FunC has the following built-in types.
+
## Atomic types
- `int` is the type of 257-bit signed integers. By default, overflow checks are enabled and lead to integer overflow exceptions.
- `cell` is the type of TVM cells. All persistent data in TON Blockchain is stored in trees of cells. Every cell has up to 1023 bits of arbitrary data and up to four references to other cells. Cells serve as memory in stack-based TVMs.
diff --git a/docs/develop/get-started-with-ton.mdx b/docs/develop/get-started-with-ton.mdx
index f50a6ed436..9dc7cf16ad 100644
--- a/docs/develop/get-started-with-ton.mdx
+++ b/docs/develop/get-started-with-ton.mdx
@@ -16,7 +16,7 @@ This learning path contains __5 modules__ and should take you around __45 minute
## 🛳 What you will learn
-In this tutorial, you'll learn how to easily make blockchain transactions using JavaScript. You could learn to do it without this tutorial, but this way is cool and accessible.
+In this tutorial, you'll learn how to easily make blockchain transactions using JavaScript. You could learn to do it without this tutorial, but this approach is convenient and user-friendly.
1. You will make your own TON Wallet with Tonkeeper
2. You will use a Testnet faucet to topup your wallet for testing
@@ -28,14 +28,16 @@ In this tutorial, you'll learn how to easily make blockchain transactions using
_You're going to mine an NFT rocket achievement!!!_
As the first miners on TON, you will go through the Proof-of-Work smart contract and finally mine a secret reward for your TON wallet. Check it out:
-
-
-
+````mdx-code-block
+
+
- Your browser does not support the video tag.
+````
+Your browser does not support the video tag.
+````mdx-code-block
-
+````
Our goal for today is to mine an NFT! This achievement will stay with you *forever*.
Finally, you are able to mine this NFT achievement even in mainnet. (_it costs only 0,05 TON!_)
@@ -56,15 +58,17 @@ Though the PoW Giver smart contract framework that defined the initial mining pr
Now, let’s focus on the first steps to becoming a **TVM Developer** and learn how to mine an NFT on TON! Provided below is an example of what we're aiming to create.
-
-
-
+
- Your browser does not support the video tag.
+````
+Your browser does not support the video tag.
+````mdx-code-block
-
+````
It’s possible to create a miner in about half an hour if we keep focused on the task at hand.
## 🦄 Getting started
@@ -80,13 +84,13 @@ To get started, all developers will make use of the following components:
To start off, you’ll need a non-custodial wallet that will allow you to receive and store your TON; for this purpose in this guide we are using Tonkeeper. You’ll need to enable Testnet mode within the wallet to be able to receive Testnet Toncoins. These tokens will be used later on to send a final minting transaction to the smart contract.
:::info
-With a non-custodial wallet, the user owns the wallet and holds its private key by themself.
+With a non-custodial wallet, the user owns the wallet and holds its private key by themselves.
:::
To download and create a TON wallet follow these simple steps:
-1. Install the Tonkeeper app on your smartphone. It can be downloaded [here](https://tonkeeper.com/).
-2. Next, you’ll need to [enable test mode](/participate/wallets/apps#tonkeeper-test-environment) within the Tonkeeper.
+1. Install the Tonkeeper app on your smartphone. It can be downloaded [here](https://Tonkeeper.com/).
+2. Next, you’ll need to [enable test mode](/participate/wallets/apps#Tonkeeper-test-environment) within Tonkeeper.
Easy! Let's go to the development now.
@@ -95,11 +99,12 @@ Easy! Let's go to the development now.
To make your life easier and skip routine low-level stuff, we will use a boilerplate.
:::tip
-Note, you need to [sign in](https://github.com/login) to GitHub for further work.
+Note, you'll need to [sign in](https://github.com/login) to GitHub for further work.
:::
Please, use the [ton-onboarding-challenge](https://github.com/ton-community/ton-onboarding-challenge) template to create your project by clicking on the “Use this template” button and selecting the “Create a new repository” tab as shown below:
+````mdx-code-block
-
+````
After completing this step, you’ll have access to a highly performant repository that can be used as your miner's core. Congratulations! ✨
### Development Environments
@@ -120,6 +125,7 @@ The next step is to choose which developer environment is best suited to your ne
Make sure you have opened the repository in your GitHub profile that was generated from the template in the previous step.
:::
+````mdx-code-block
-
+````
#### Local and Cloud Development Environments
-* For users unfamiliar with JavaScript, it is not usually possible to leverage a JavaScript IDE, especially if your computer and tooling systems are not tailored to using such an approach. It is often faster and more efficient to use a **cloud environment** for development. Cloud environments are often free and readily available on GitHub for anyone to use with a few simple clicks.
+* For users who are not familiar with JavaScript, it can be challenging to use a JavaScript IDE, especially if your computer and tooling systems are not configured for this purpose.
* However, if you're familiar with NodeJS and Git and know how to work with `npm`, it may be more comfortable for you to use a **local environment**.
@@ -140,6 +146,7 @@ Make sure you have opened the repository in your GitHub profile that was generat
If you choose the cloud development environment it's easy to get started by first selecting the _Code_ tab and then by clicking on the _Create codespace on master_ button within the GitHub repository like shown below:
+````mdx-code-block
-
+````
After completing this step, GitHub will create a special cloud workspace that allows you to access the VSCode Online IDE (Visual Code Online Integrated Development Environment).
-After this access is granted (it takes about 30 seconds for the terminal to install) you'll have everything you need to get started without needing to install Git, Node.js, or other developer tools.
+Once access is granted (the codespace typically starts in about 30 seconds), you'll have everything required to begin without the need to install Git, Node.js, or other developer tools.
#### Local Development Environments
-To begin using a local development environment you’ll need access to 3 main tools. These include:
+To set up a local development environment, you'll require access to these three essential tools:
- **Git**: Git is an essential tool that every developer needs to work with repositories. It can be downloaded [here](https://git-scm.com/downloads).
- **NodeJS**: Node.js is the JavaScript and TypeScript runtime environment typically used for application development on TON. It can be downloaded [here](https://nodejs.org/en/download/).
- **JavaScript IDE**. JavaScript IDE’s are typically used for development within local development environments. An example of this case is Visual Studio Code ([VSCode](https://code.visualstudio.com/download)).
-To get started you’ll clone your GitHub repository boilerplate and open the correct repository in your Integrated Development Environment (IDE).
+To get started, you’ll need to clone your GitHub repository boilerplate and open the correct repository in your Integrated Development Environment (IDE).
#### Running Scripts
-In this guide, you will need to run a TypeScript script. All commands, such as running a script or installing a module, are inputted via the command line, which is located in the special workspace of IDE called _Terminal_. This workspace is usually located at the bottom of the IDE.
+In this guide, you'll need to run TypeScript scripts. All commands, such as running scripts or installing modules, are executed through the command line, which is located in the IDE's Terminal workspace. This workspace is typically found at the bottom of the IDE.
For example, in the Cloud Codespaces, you should open the Terminal workspace (if it is not already open):
+````mdx-code-block
+````
+Enter commands in this window and execute them with _Enter_:
-Input commands in this window and execute them with _Enter_:
-
+````mdx-code-block
-
+````
The Terminal is also available as a separate application. Please choose the appropriate version based on your IDE and OS.
Great! After these steps you're ready to get deeper into TON Blockchain secrets. 👀
@@ -203,16 +212,16 @@ Okay, what do you need to connect to TON Blockchain?
* __Smart contract address__ as a point of destination. Our goal is to mine an NFT from the _proof-of-work smart contract_, so we need an address to get current mining complexity.
* __API provider__ to make requests to TON Blockchain. TON has multiple [API types](/develop/dapps/apis/) for different purposes. We will use the testnet version of [toncenter.com](https://toncenter.com/) API.
-* __JavaScript SDK__: A JavaScript SDK (recall that an SDK is a software development kit) is needed to parse the smart contract address being used and prepare it to create an API request. To better understand TON addresses and why they need to be parsed to carry out this process, please see this [resource](/learn/overviews/addresses) to understand why we should parse it. To carry out this procedure the [ton.js](https://github.com/ton-core/ton) will be used.
+* __JavaScript SDK__: A JavaScript SDK (recall that an SDK is a Software Development Kit) is needed to parse the smart contract address being used and prepare it to create an API request. To better understand TON addresses and why they need to be parsed to carry out this process, please see this [resource](/learn/overviews/addresses) to understand why should we parse it. To carry out this procedure, we'll use [ton.js](https://github.com/ton-core/ton).
-In the next section we’ll describe how users send their initial requests to TON Blockchain using the toncenter API and ton.js to receive data from the PoW smart contract.
+In the next section we’ll describe how users send their initial requests to TON Blockchain using the TONCenter API and ton.js to receive data from the PoW smart contract.
### Smart Contract Addresses
For the miner to work correctly, we need to add two different smart contract address types. These include:
-1. __Wallet address__: A wallet address is required because it is necessary for the miner to receive their mining reward (in this case, we must use the [Tonkeeper Testnet mode](/participate/wallets/apps#tonkeeper-test-environment)).
-2. __Collection address__: A collection address is required to act as a smart contract to correctly mine an NFT (to carry out this process copy the NFT collection address, under the TON unboarding challenge collection name from the [Getgems website](https://testnet.getgems.io/collection/EQDk8N7xM5D669LC2YACrseBJtDyFqwtSPCNhRWXU7kjEptX)).
+1. __Wallet address__: A wallet address is required, because it is necessary for the miner to receive their mining reward (in this case, we must use the [Tonkeeper Testnet mode](/participate/wallets/apps#Tonkeeper-test-environment)).
+2. __Collection address__: A collection address is required to act as a smart contract to correctly mine an NFT (to carry out this process copy the NFT collection address, under the TON onboarding challenge collection name from the [Getgems website](https://testnet.getgems.io/collection/EQDk8N7xM5D669LC2YACrseBJtDyFqwtSPCNhRWXU7kjEptX)).
Next, we’ll open the `index.ts` file in your miner and create a main function composed of initial constants as follows:
@@ -244,14 +253,15 @@ The `Address.parse()` command found in the `ton.js` SDK allows the developer to
### Connect to an API Provider
-In this step, we'll connect with TON via toncenter (which is hosted on toncenter.com) API provider using specific commands in the script.
+In this step, we'll connect with TON via TONCenter (which is hosted on toncenter.com) API provider using specific commands in the script.
The simplest way to learn how it works is by using @orbs-network/ton-access.
:::tip
-Remember, if you are adding new modules with `import`, that You may need to install them by executing the command `npm i @orbs-network/ton-access` in the [terminal](/develop/get-started-with-ton#running-scripts).
+Remember, if you are adding new modules with `import`, that you may need to install them by executing the command `npm i @orbs-network/ton-access` in the [terminal](/develop/get-started-with-ton#running-scripts).
:::
+````mdx-code-block
-
+````
We are adding `client` and `endpoint` in the `index.ts` script using _TonClient_ and _getHttpEndpoint_ from `@orbs-network/ton-access`:
@@ -282,7 +292,7 @@ import {getHttpEndpoint} from "@orbs-network/ton-access";
```
:::info what to do in production?
-It's better to use an RPC node provider or to run your own ton-http-api instance for that. Read more at the [TonCenter API page](/develop/dapps/apis/toncenter).
+It's better to use an RPC node provider, or to run your own ton-http-api instance for that. Read more at the [TonCenter API page](/develop/dapps/apis/toncenter).
:::
### Receiving Mining Data From TON Blockchain
@@ -329,7 +339,7 @@ npm run start
To avoid unexpected issues, make sure you have finalized all previous steps, including inputting contract addresses.
:::
-Good! As long as the above processes were executed correctly, successful connection to the API will be achieved and the necessary data will be received within the console. The correct console output should be initiated as follows:
+Good! As long as the above processes were executed correctly, successful connection to the API will be achieved and the necessary data will be displayed in the console. The correct console output should be initiated as follows:
```bash
{
@@ -348,13 +358,13 @@ Good! As long as the above processes were executed correctly, successful connect
}
```
-Above it displays the gas amount used to execute the process as well as the sum of numerical (_num_) values in hex format. At this time, this data is not too critical because it is necessary to convert the hex output data into something that can be used more easily.
+Above it displays the gas amount used to execute the process, as well as the sum of numerical (_num_) values in hex format. At this time, this data is not too critical because it is necessary to convert the hex output data into something that can be used more easily.
We need to convert the hex output to something _useful_.
:::info GAS PARAMETERS ON TON:
__Warning__: Though this information is highly complex and __not necessary for this tutorial__, if you’re interested in understanding the complex technical aspects of TON consider using these resources:
-1. To obtain a better understanding of how TON Virtual Machine (TVM) operates and _how transactions on TON work_, check out [TVM overview section](/learn/tvm-instructions/tvm-overview).
+1. To obtain a better understanding of how TON Virtual Machine (TVM) operates and _how does TON process transactions_, check out [TVM overview section](/learn/tvm-instructions/tvm-overview).
2. Secondly, if you are interested in learning more about how transaction and gas fees work on TON, consider diving into [this section](/develop/smart-contracts/fees) of our documentation.
3. Finally, to get a better understanding of the exact gas values needed to carry out TVM instructions see [this section](/learn/tvm-instructions/instructions#gas-prices) of our documentation.
:::
@@ -363,9 +373,9 @@ Now, let's return to the tutorial!
#### Numerical Mining Data in a User-Friendly Format
-In the section above where we discuss gas amounts and numerical (_num_) values in hex format needed to receive mining data, we note that the hex numbers present within the strings of code must be converted into a more easily understood and usable format.
+In the section above where we discuss gas amounts and numerical (_num_) values in hex format needed to receive mining data, we note that the hex numbers present within the strings of code must be converted into a more easily understandable and usable format.
-As is clear when examining the given output, hex numbers can be quite substantial in size. It's not possible to move them to the variable and make use of them, because of specific [JavaScript limitations](https://stackoverflow.com/questions/307179/what-is-javascripts-highest-integer-value-that-a-number-can-go-to-without-losin#:~:text=Note%20that%20the%20bitwise%20operators,31%2D1%2C%20or%202%2C147%2C483%2C647.) that are outlined here.
+As it is clear when examining the given output, hex numbers can be quite substantial in size. It's not possible to make a variable and make use of them, because of specific [JavaScript limitations](https://stackoverflow.com/a/307200) that are outlined here.
We need a way to translate this, that’s where the `bn.js` (the big number implementation in JavaScript) library comes in. Bn.js is a library developers use to work with large numbers that are larger than the maximum JavaScript integer values. Let’s use this example to get a better idea of the _Mining Data_ required for this process:
@@ -414,7 +424,7 @@ max_cpl 252
Let's cover the Mining Data command that is used to translate different data parameters when programming mining data into TON Blockchain. These include:
* `complexity` is the most important number for miners. It's a Proof-of-Work complexity for the values. You're successful _if the final hash is less than complexity_.
-* `last_success` is a [unix time](https://www.unixtimestamp.com/) date and time representation that keeps track of the last mining transaction on TON. Each time the last_success metric changes, it's necessary to run the miner again because the seed also changes during this process.
+* `last_success` is a [unix timestamp](https://www.unixtimestamp.com/) date and time representation that keeps track of the last mining transaction on TON. Each time the last_success metric changes, it's necessary to run the miner again because the seed also changes during this process.
* `seed` denotes a unique value generated by a smart contract to calculate the desired hash. To better understand this process and learn more about how the seed changes and why, have a look at the project files folder by using the ctx_seed keyword(Ctrl+F with keyword "ctx_seed").
* `target_delta`, `min_cpl` and `max_cpl` won't be used in our tutorial. But you can always read more about how they are used in smart contracts to calculate proof-of-work complexity in the source files of the collection in your project.
@@ -422,7 +432,7 @@ Now that we understand the different parameters discussed above, we have the val
## 🛠 Prepare a NFT Miner
-Hey, you did a great job!
+Hey, you're doing a great job!
After connecting to TON and retrieving the necessary mining data from the blockchain to create an NFT Miner, let’s focus on the next steps in this process to achieve our goal.
@@ -432,15 +442,15 @@ That is what a miner is! Simple, isn't it?
### Preparing Mining Messages
-Next, we must prepare a mining message by ensuring the correct parameters to ensure the validity and data legitimacy of this process.
+First, we must prepare a mining message by ensuring the correct parameters to ensure the validity and data integrity of this process.
Thankfully, the [README file](https://github.com/ton-community/ton-onboarding-challenge#mining-process-advanced) allows us to retrieve the correct guidelines needed to achieve this goal. As you can see, the above README file comprises a table with certain fields and Cell types (titled “Layout of Proof of Work Cell’) to help achieve our desired result.
:::info WHAT ARE CELLS?
-Cells are data storage structures on TON that fulfill numerous purposes including increasing network scalable and smart contract transaction speeds. We won’t get into specifics here, but if you’re interested in understanding the complexity of cells and how they work, consider diving into [this](/learn/overviews/cells) section of our documentation.
+Cells are data storage structures on TON that fulfill numerous purposes, including increasing network scalable and smart contract transaction speeds. We won’t get into specifics here, but if you’re interested in understanding the complexity of cells and how they work, consider diving into [this](/learn/overviews/cells) section of our documentation.
:::
-Luckily, all data structures used in this process have already been written with TypeScript for this tutorial. Use a `MineMessageParams` object from _NftGiver.data.ts_ to build a transaction with _Queries_:
+Fortunately, all the data structures used in this tutorial are already written in TypeScript. Use the `MineMessageParams` object from _NftGiver.data.ts_ to build a transaction with _Queries_:
```ts title="ton-onboarding-challenge/index.ts"
import {unixNow} from "./src/lib/utils";
@@ -458,7 +468,7 @@ Luckily, all data structures used in this process have already been written with
let msg = Queries.mine(mineParams); // transaction builder
```
-Probably, you have a question: where is the _op_ and _data2_ from the [table](https://github.com/ton-community/ton-onboarding-challenge#mining-process-advanced)?
+Probably, you have a question: where are the _op_ and _data2_ from the [table](https://github.com/ton-community/ton-onboarding-challenge#mining-process-advanced)?
* In the table, the numerical value of data1 must be equal to that of data2. In order to omit filling the data2 value, the transaction builder performs a low-level process (see Queries.mine() sources).
* Because the `op` classification is always constant, it is already implemented in transaction builder _Queries_ and in _OperationCodes_. You can find the op code by going to the source code of `mine()` method.
@@ -476,7 +486,7 @@ let msg = Queries.mine(mineParams);
Above we compiled a `msg` value. The idea of mining is to find a hash `msg.hash()` that will be less than `complexity` from the last received _get_mining_data()_. We can increment `data1` as many times as we need.
-The pure miner will continue to run infinitely as long as the `msg.hash() > complexity` (message hash is larger than PoW mining complexity).
+The pure miner will continue to run indefinitely, as long as `msg.hash()` is bigger than `complexity` (message hash is larger than PoW mining complexity).
Here is an example of the code running as it relates to BigNumbers in TypeScript:
@@ -497,11 +507,11 @@ A few important considerations regarding Big Number (_BN_) functions:
* `gt()`: denotes _greater than a variable_ for comparing _BigNumbers_.
* `iaddn(1)`: denotes an incremented value.
-Though the miner will work properly after the completion of the above steps, it will appear very poor visually (try `npm run start`). Therefore, we must address this issue. Let’s jump in.
+Though the miner will work properly after the completion of the above steps, it will have a visually unappealing appearance (try `npm run start`). Therefore, we must address this issue. Let’s jump in.
#### Improving TON Miner Appearance ✨
-We want to make the miner sexy now! How do we do it?
+We want to make the miner look sexy now! How do we do it?
Just follow me, my friend, follow me.
@@ -537,6 +547,7 @@ Just check it out! Let’s execute the command:
npm run start
```
+````mdx-code-block
-
+````
_Cool, isn't it?_ 😏
-After these commands are executed correctly, we’ll have a visually appealing NFT miner. In the next section, we’ll focus on connecting a wallet with the miner to create a payment channel that can accept and receive transactions from TON Blockchain.
+After these commands are executed correctly, we’ll have a visually appealing NFT miner. In the next section, we’ll focus on connecting a wallet to the miner to create a payment channel that can accept and receive transactions from TON Blockchain.
## 🎨 Prepare a Transaction
-Next we’ll outline the steps to compile a message and send it to the blockchain with your [Tonkeeper wallet](https://tonkeeper.com/).
-The upcoming steps will help complete the process of __mining an NFT__ on TON.
+Next, we’ll outline the steps to compile a message and send it to the blockchain with your [Tonkeeper wallet](https://Tonkeeper.com/).
+The upcoming steps will guide you in completing the process of __mining an NFT__ on TON.
### Creating a Payment Link
-In order to ensure that the NFT mining process is carried out correctly and that the user can store their NFT properly, we must create a payment link that is able to simultaneously interact with TON Blockchain and the Tonkeeper wallet.
+In order to ensure that the NFT mining process is carried out correctly, and that the user can store their NFT properly, we must create a payment link that is able to simultaneously interact with TON Blockchain and the Tonkeeper wallet.
-To achieve this goal, we’ll initiate the creation of a payment url (a payment link) using the `ton://transfer/` format that can be customized using different parameters. This will work perfectly because we want to create a message and send it to the smart contract within our Tonkeeper wallet:
+To achieve this goal, we’ll initiate the creation of a payment URL (a payment link) using the `ton://transfer/` format that can be customized using different parameters. This will work perfectly because we want to create a message, and send it to the smart contract using our Tonkeeper wallet:
```ts title="ton-onboarding-challenge/index.ts"
import {toNano} from "ton"
@@ -570,8 +581,8 @@ import {toNano} from "ton"
// ... previous code
console.log(' ');
- console.log("💣 WARNING! As soon as you find the hash, you should quickly make a transaction.");
- console.log("If someone else makes a transaction, the seed changes, and you have to find a hash again!");
+ console.log("💣 WARNING! As soon as you find the hash, you should quickly send the transaction.");
+ console.log("If someone else sends a transaction before you, the seed changes, and you'll have to find the hash again!");
console.log(' ');
// flags work only in user-friendly address form
@@ -584,7 +595,7 @@ import {toNano} from "ton"
// BOC means Bag Of Cells here
const preparedBodyCell = msg.toBoc().toString('base64url')
- // final method to build a payment url
+ // final method to build a payment URL
const tonDeepLink = (address: string, amount: string, body: string) => {
return `ton://transfer/${address}?amount=${amount}&bin=${body}`;
};
@@ -595,11 +606,11 @@ import {toNano} from "ton"
console.log(link);
```
-Let’s run the above script to launch the newly created payment link. Now it’s time to make the payment link running on your PC smart phone compatible. Let’s get started.
+Let’s run the above script to launch the newly created payment link. Now it’s time to make the payment link running on your PC smartphone compatible. Let’s get started.
### Creating A Smartphone Compatible Payment Link
-As a solution, the most brilliant minds in the world created a QR code generator specifically for use in terminal. With this tool, you can simply scan the payment link from your Tonkeeper wallet to complete a transaction.
+As a solution, the most brilliant minds in the world created a QR code generator specifically for use in terminal. With this tool, you can simply scan the payment link from your Tonkeeper wallet to send a transaction.
```bash
npm install qrcode-terminal
@@ -620,7 +631,7 @@ Finally, we’ll need to encode the payment link(`link`) into the QR code and pr
Do you sense the _experience_ in the air? That's you, on your way to becoming a TVM developer.
-Now that we have successfully encoded the QR code generator and payment link, we'll need to acquire some Testnet Toncoins to send our first transaction. This is accomplished by making use of a TON [token faucet](https://coinmarketcap.com/alexandria/glossary/faucet) (a Telegram Bot that shares Testnet Toncoins) on TON Blockchain so we are in possession of some tokens that can be sent to the Tonkeeper wallet we created.
+Now that we have successfully encoded the QR code generator and payment link, we'll need to acquire some Testnet Toncoins to send our first transaction. This is accomplished by making use of a TON [token faucet](https://coinmarketcap.com/alexandria/glossary/faucet) (a Telegram Bot that shares Testnet Toncoins) on TON Blockchain, so we are in possession of some tokens that can be sent to the Tonkeeper wallet we created.
## ⛏ Mine an NFT With a Wallet
@@ -634,11 +645,11 @@ There are two main ways to mine an NFT on TON:
Below are the steps needed to initiate your first Testnet transaction to mine your NFT:
-1. Activate [Testnet mode within your Tonkeeper wallet](/participate/wallets/apps#tonkeeper-test-environment)
+1. Activate [Testnet mode within your Tonkeeper wallet](/participate/wallets/apps#Tonkeeper-test-environment)
2. Input our testnet wallet address from Tonkeeper into `wallet` variable in the `index.ts`
3. Input address of the [NFT collection from Testnet](https://testnet.getgems.io/collection/EQDk8N7xM5D669LC2YACrseBJtDyFqwtSPCNhRWXU7kjEptX) into `collection` variable in the `index.ts`
-#### Top Up Wallet Balance via a Token Faucet
+#### Top Up Wallet Balance via the Token Faucet
To proceed to the next step, we need to acquire some TON testnet tokens. This can be achieved by making use of the testnet [faucet found here](https://t.me/testgiver_ton_bot).
@@ -646,7 +657,7 @@ To proceed to the next step, we need to acquire some TON testnet tokens. This ca
In order to successfully mine an NFT rocket on Testnet, it is necessary to follow these steps:
-1. _Open_ Open the Tonkeeper wallet on your smartphone (it should hold some newly received TON Testnet tokens).
+1. _Open_ Open the Tonkeeper wallet on your phone (it should hold some newly received TON Testnet tokens).
2. _Select_ scan mode in the wallet to scan the QR code.
3. _Run_ your miner to acquire the correct hash (this process takes between 30 and 60 seconds).
4. _Scan_ the generated QR code from the miner.
@@ -681,7 +692,7 @@ const endpoint = await getHttpEndpoint();
Like we outlined in the testnet NFT rocket mining process, in order to successfully mine an NFT rocket on mainnet, it is necessary to follow these steps:
-1. _Open_ the Tonkeeper wallet on your smartphone (remember, it should hold some TON tokens).
+1. _Open_ the Tonkeeper wallet on your phone (remember, it should hold some TON tokens).
2. _Select_ scan mode in the wallet to scan the QR code.
3. _Run_ your miner to acquire the correct hash (this process takes between 30 and 60 seconds).
4. _Scan_ the generated QR code from the miner.
@@ -691,14 +702,16 @@ Because there may be other developers carrying out the same process in an attemp
:::
After some time, you will have __mined your NFT__ and become a TVM Developer in TON Blockchain. The ritual is complete. Look at your NFT in Tonkeeper.
-
-
-
+````mdx-code-block
+
+
- Your browser does not support the video tag.
+````
+Your browser does not support the video tag.
+````mdx-code-block
-
+````
Welcome aboard, __a TVM Developer__! You did it. 🛳
diff --git a/docs/develop/howto/blockchain-configs.md b/docs/develop/howto/blockchain-configs.md
index b04616b048..4668fd0fb2 100644
--- a/docs/develop/howto/blockchain-configs.md
+++ b/docs/develop/howto/blockchain-configs.md
@@ -1,6 +1,8 @@
-# Blockchain Config
+# Config Parameters
-#### The Russian version of this article can be found [here](https://github.com/delovoyhomie/description-config-for-TON-Blockchain/blob/main/Russian-version.md).
+:::info
+Read live values via [tonviewer](https://tonviewer.com/config)
+:::
## 👋 Introduction
@@ -108,7 +110,7 @@ This parameter indicates under what conditions proposals to change the TON confi
This parameter represents the configuration of a workchain in the TON Blockchain. Workchains in the TON Blockchain are designed as independent blockchains that can operate in parallel, allowing TON to scale and process a very large number of transactions and smart contracts.
-## Workchain configuration parameters:
+## Workchain configuration parameters
- `enabled_since`: a UNIX timestamp of the moment this workchain was enabled;
@@ -147,7 +149,7 @@ This parameter contains the duration of different stages of elections and valida
For each validation period, there is an `election_id` equal to the UNIX-format time at the start of the validation.
You can get the current `election_id` (if elections are ongoing) or the past one by invoking the Elector contract's respective get-methods `active_election_id` and `past_election_ids`.
-## Workchain configuration parameters:
+## Workchain configuration parameters
- `validators_elected_for`: the number of seconds the elected set of validators perform their role (one round).
@@ -167,7 +169,7 @@ In the TON Blockchain, it is customary to conventionally divide validation perio
#### Mainnet
-##### Current values:
+Current values:
```python
constants = {
@@ -178,7 +180,7 @@ constants = {
}
```
-##### Scheme
+Scheme:
![image](/img/docs/blockchain-configs/config15-mainnet.png)
@@ -482,6 +484,18 @@ This parameter defines the list of suspended addresses, which cannot be initiali
The stabilization of the tokenomics is further described in the [official report](https://t.me/tonblockchain/178) of the "The Open Network" Telegram channel.
:::
+## Param 45
+
+The list of precompiled contracts is stored in the masterchain config:
+
+```
+precompiled_smc#b0 gas_usage:uint64 = PrecompiledSmc;
+precompiled_contracts_config#c0 list:(HashmapE 256 PrecompiledSmc) = PrecompiledContractsConfig;
+_ PrecompiledContractsConfig = ConfigParam 45;
+```
+
+More details about precompiled contracts on [this page](/develop/smart-contracts/core-contracts/precompiled).
+
## Param 71 - 73
This parameter pertains to bridges for wrapping TON in other networks:
@@ -540,3 +554,4 @@ On this page, you can find active network configurations of the TON Blockchain:
- Mainnet: https://ton.org/global-config.json
- Testnet: https://ton.org/testnet-global.config.json
+- [Russian Version](https://github.com/delovoyhomie/description-config-for-TON-Blockchain/blob/main/Russian-version.md).
diff --git a/docs/develop/howto/compile.md b/docs/develop/howto/compile.md
index 4418fdd685..df0f7f50c3 100644
--- a/docs/develop/howto/compile.md
+++ b/docs/develop/howto/compile.md
@@ -25,13 +25,13 @@ git clone --recurse-submodules https://github.com/ton-blockchain/ton.git
- `cmake` version 3.0.2 or later
- `g++` or `clang` (or another C++14-compatible compiler as appropriate for your operating system).
- OpenSSL (including C header files) version 1.1.1 or later
- - `build-essential`, `zlib1g-dev`, `gperf`, `libreadline-dev`, `ccache`, `libmicrohttpd-dev`, `pkg-config`
+ - `build-essential`, `zlib1g-dev`, `gperf`, `libreadline-dev`, `ccache`, `libmicrohttpd-dev`, `pkg-config`, `libsodium-dev`, `libsecp256k1-dev`
- On Ubuntu:
+### On Ubuntu
```bash
apt update
-sudo apt install build-essential cmake clang openssl libssl-dev zlib1g-dev gperf libreadline-dev ccache libmicrohttpd-dev pkg-config
+sudo apt install build-essential cmake clang openssl libssl-dev zlib1g-dev gperf libreadline-dev ccache libmicrohttpd-dev pkg-config libsodium-dev libsecp256k1-dev
```
@@ -50,23 +50,58 @@ export CXX=clang++
cmake -DCMAKE_BUILD_TYPE=Release ../ton && cmake --build . -j$(nproc)
```
-:::warning
-On MacOS Intel before next step we need maybe install `openssl@3` with `brew` or just link the lib:
+### On MacOS
+Prepare the system by installing required system packages
```zsh
-brew install openssl@3 ninja libmicrohttpd pkg-config
+brew install ninja libsodium libmicrohttpd pkg-config automake libtool autoconf gnutls
+brew install llvm@16
```
-Then need to inspect `/usr/local/opt`:
+Use newly installed clang.
+```zsh
+ export CC=/opt/homebrew/opt/llvm@16/bin/clang
+ export CXX=/opt/homebrew/opt/llvm@16/bin/clang++
+```
+
+Compile secp256k1
+```zsh
+ git clone https://github.com/bitcoin-core/secp256k1.git
+ cd secp256k1
+ secp256k1Path=`pwd`
+ git checkout v0.3.2
+ ./autogen.sh
+ ./configure --enable-module-recovery --enable-static --disable-tests --disable-benchmark
+ make -j12
+```
+and lz4:
+
+```zsh
+ git clone https://github.com/lz4/lz4
+ cd lz4
+ lz4Path=`pwd`
+ git checkout v1.9.4
+ make -j12
+```
+and relink OpenSSL 3.0
```zsh
-ls /usr/local/opt
+brew unlink openssl@1.1
+brew install openssl@3
+brew unlink openssl@3 && brew link --overwrite openssl@3
```
-Find `openssl@3` lib and export local variable:
+Now you can compile TON
```zsh
-export OPENSSL_ROOT_DIR=/usr/local/opt/openssl@3
+cmake -GNinja -DCMAKE_BUILD_TYPE=Release .. \
+-DCMAKE_CXX_FLAGS="-stdlib=libc++" \
+-DSECP256K1_FOUND=1 \
+-DSECP256K1_INCLUDE_DIR=$secp256k1Path/include \
+-DSECP256K1_LIBRARY=$secp256k1Path/.libs/libsecp256k1.a \
+-DLZ4_FOUND=1 \
+-DLZ4_LIBRARIES=$lz4Path/lib/liblz4.a \
+-DLZ4_INCLUDE_DIRS=$lz4Path/lib
```
:::
diff --git a/docs/develop/howto/config-params.md b/docs/develop/howto/config-params.md
index 2967776153..63bec539c1 100644
--- a/docs/develop/howto/config-params.md
+++ b/docs/develop/howto/config-params.md
@@ -1,10 +1,8 @@
-# Config Params
+# Changing the Parameters
-:::caution
-This section describes instructions and manuals for interacting with TON at a low level. Learn friendly explained config [params here](/develop/howto/blockchain-configs).
-:::
+The aim of this document is to provide a basic explanation of configuration parameters of TON Blockchain, and to give step-by-step instructions for changing these parameters by a consensus of a majority of validators.
-The aim of this document is to provide a basic explanation of configuration parameters of TON Blockchain, and to give step-by-step instructions for changing these parameters by a consensus of a majority of validators. We assume that the reader is already familiar with Fift and the Lite Client as explained in [LiteClient-HOWTO](https://toncoin.org/#/howto/step-by-step), with [FullNode-HOWTO](https://toncoin.org/#/howto/full-node), and [Validator-HOWTO](https://toncoin.org/#/howto/validator) in the sections where validators' voting for the configuration proposals is described.
+We assume that the reader is already familiar with [Fift](/develop/fift/overview) and the [Lite Client](/participate/nodes/lite-client), as explained in [FullNode-HOWTO (low-level)](/participate/nodes/full-node), and [Validator-HOWTO (low-level)](/participate/nodes/validator) in the sections where validators' voting for the configuration proposals is described.
## 1. Configuration parameters
The **configuration parameters** are certain values that affect the behavior of validators and/or fundamental smart contracts of TON Blockchain. The current values of all configuration parameters are stored as a special part of the masterchain state and are extracted from the current masterchain state when needed. Therefore, it makes sense to speak of the values of the configuration parameters with respect to a certain masterchain block. Each shardchain block contains a reference to the latest known masterchain block; the values from the corresponding masterchain state are assumed to be active for this shardchain block and are used during its generation and validation. For masterchain blocks, the state of the previous masterchain block is used to extract the active configuration parameters. Therefore, even if one tries to change some configuration parameters inside a masterchain block, the changes will become active only for the next masterchain block.
@@ -262,8 +260,8 @@ Voting for a configuration proposal is possible only for current validators, lis
Vm90RQAAjvFgMYDa1bWZ-oVIBpkaeqnygNvbgdZ84b7f-dZhKKE=
Saved to file validator-to-sign.req
```
-- After that, the vote request has to be signed by the current validator's private key, using `sign 566F744...28A1` in `validator-engine-console` connected to the validator. This process is similar to that described in [Validator-HOWTO](https://toncoin.org/#/howto/validator) for participating in validator elections, but this time the currently active key has to be used.
-- Next, another script `config-proposal-signed.fif` has to be invoked. It has similar arguments to `config-proposal-req.fif`, but it expects two extra arguments: the base64 representation of the public key used to sign the vote request, and the base64 representation of the signature itself. Again, this is quite similar to the process described in [Validator-HOWTO](https://toncoin.org/#/howto/validator).
+- After that, the vote request has to be signed by the current validator's private key, using `sign 566F744...28A1` in `validator-engine-console` connected to the validator. This process is similar to that described in [Validator-HOWTO](/participate/nodes/validator) for participating in validator elections, but this time the currently active key has to be used.
+- Next, another script `config-proposal-signed.fif` has to be invoked. It has similar arguments to `config-proposal-req.fif`, but it expects two extra arguments: the base64 representation of the public key used to sign the vote request, and the base64 representation of the signature itself. Again, this is quite similar to the process described in [Validator-HOWTO](/participate/nodes/validator).
- In this way, the file `vote-msg-body.boc` containing the body of an internal message carrying a signed vote for this configuration proposal is created.
- After that, `vote-msg-body.boc` has to be carried in an internal message from any smart contract residing in the masterchain (typically, the controlling smart contract of the validator will be used) along with a small amount of Toncoin for processing (typically, 1.5 Toncoin should suffice). This is again completely similar to the procedure employed during validator elections. This is typically achieved by means of running:
```
@@ -286,7 +284,7 @@ This time, the list of indices of validators that voted for this configuration p
## 5. An automated way for voting on configuration proposals
-Similarly to the automation provided by command `createelectionbid` of `validator-engine-console` for participating in validator elections, `validator-engine` and `validator-engine-console` offer an automated way of performing most of the steps explained in the previous section, producing a `vote-msg-body.boc` ready to be used with the controlling wallet. In order to use this method, you must install the Fift scripts `config-proposal-vote-req.fif` and `config-proposal-vote-signed.fif` into the same directory that the validator-engine uses to look up `validator-elect-req.fif` and `validator-elect-signed.fif` as explained in Section 5 of [Validator-HOWTO](https://toncoin.org/#/howto/validator). After that, you simply run
+Similarly to the automation provided by command `createelectionbid` of `validator-engine-console` for participating in validator elections, `validator-engine` and `validator-engine-console` offer an automated way of performing most of the steps explained in the previous section, producing a `vote-msg-body.boc` ready to be used with the controlling wallet. In order to use this method, you must install the Fift scripts `config-proposal-vote-req.fif` and `config-proposal-vote-signed.fif` into the same directory that the validator-engine uses to look up `validator-elect-req.fif` and `validator-elect-signed.fif` as explained in Section 5 of [Validator-HOWTO](/participate/nodes/validator). After that, you simply run
```
createproposalvote 64654898543692093106630260209820256598623953458404398631153796624848083036321 vote-msg-body.boc
```
diff --git a/docs/develop/howto/faq.md b/docs/develop/howto/faq.md
index 7724a13269..914b2d2647 100644
--- a/docs/develop/howto/faq.md
+++ b/docs/develop/howto/faq.md
@@ -20,6 +20,28 @@ This section covers the most popular questions about TON Blockchain.
- [Testnet](/develop/smart-contracts/environment/testnet)
+## TON and L2
+
+### Why is workchains better than L1 → L2?
+
+Workchains in TON, offer a number of advantages over traditional L1 and L2 layer architecture.
+
+1. One of the key advantages of a blockchain is the instantaneous processing of transactions. In traditional L2 solutions, there can be delays in moving assets between layers. Workchains eliminate this problem by providing seamless and instantaneous transactions between different parts of the network. This is especially important for applications requiring high speed and low latency.
+2. Workchains support cross-shard activity, which means that users can interact between different shardchains or workchains within the same network. In current L2 solutions, cross-shard operations are often complex and require additional bridges or interoperability solutions. In TON, for example, users can easily exchange tokens or perform other transactions between different shardchains without complex procedures.
+3. Scalability is one of the main challenges for modern blockchain systems. In traditional L2 solutions, scalability is limited by the capacity of the sequencer. If the TPS (transactions per second) on L2 exceeds the sequencer's capacity, it can lead to problems. In workchains in TON, this problem is solved by dividing the shard. When the load on a shard exceeds its capacity, the shard is automatically divided into two or more shards, allowing the system to scale almost without limit.
+
+### Is there a need for L2 on the TON?
+
+At any transaction cost, there will always be applications that cannot sustain such a fee but can function at a much lower cost. Similarly, regardless of the latency achieved, there will always be applications that require even lower latency. Therefore, it is conceivable that there might eventually be a need for L2 solutions on the TON platform to cater to these specific requirements.
+
+## MEV
+
+### Is front running possible in TON?
+
+In the TON blockchain, deterministic transaction order plays a key role in preventing frontrunning. This means that the order of transactions within a blockchain is predetermined and deterministic. No participant can change this order once transactions have entered the pool. This system eliminates the possibility of manipulating the order of transactions for profit, which differentiates TON from other blockchains such as Ethereum, where validators can change the order of transactions within a block, creating opportunities for MEV (maximum extractable value).
+
+In addition, the current TON architecture lacks a market-based mechanism for determining transaction fees. Commissions are fixed and not subject to change depending on transaction priorities, which makes frontrunning less attractive. Because of the fixed fees and deterministic order of transactions, it is non-trivial to do frontrunning in TON.
+
## Block
### What is the RPC method used to retrieve block information?
@@ -41,16 +63,20 @@ Read more in the [Explorers in TON](/participate/explorers) section of our docum
_2-5s_
:::info
-Compare TON's on-chain metrics, including block time and time-to-finality, to Solana and Ethereum by reading our analysis at [ton.org/analysis](https://ton.org/analysis).
-:::
+Compare TON's on-chain metrics, including block time and time-to-finality, to Solana and Ethereum by reading our analysis at:
+* [Comparison of Blockchains document](https://ton.org/comparison_of_blockchains.pdf)
+* [Comparison of Blockchains table (much less informative than the document, but more visual)](/learn/overviews/blockchain-comparison)
+ :::
### Time-to-finality
_Under 6 sec._
:::info
-Compare TON's on-chain metrics, including block time and time-to-finality, to Solana and Ethereum by reading our analysis at [ton.org/analysis](https://ton.org/analysis).
-:::
+Compare TON's on-chain metrics, including block time and time-to-finality, to Solana and Ethereum by reading our analysis at:
+* [Comparison of Blockchains document](https://ton.org/comparison_of_blockchains.pdf)
+* [Comparison of Blockchains table (much less informative than the document, but more visual)](/learn/overviews/blockchain-comparison)
+ :::
### Average block size
@@ -194,6 +220,23 @@ To protect message chains from being halted at non-existing contracts TON use "b
- [Deploying wallet via TonLib](https://ton.org/docs/develop/dapps/asset-processing/#deploying-wallet)
- [Paying for processing queries and sending responses](https://ton.org/docs/develop/smart-contracts/guidelines/processing)
+### Does the upgradability of a smart-contract pose a threat to its users?
+
+Currently, the ability to update smart contracts is a normal practice and is widely used in most modern protocols. This is because updatability allows for bug fixes, adding new features and improving security.
+
+How to mitigate the risks:
+
+1. Pay attention to projects with a good reputation and well-known development teams.
+2. Reputable projects always conduct independent code audits to make sure the code is safe and reliable. Look for projects that have several completed audits from reputable auditing firms.
+3. An active community and positive feedback can serve as an additional indicator of a project's reliability.
+4. Examine exactly how the project implements the update process. The more transparent and decentralized the process, the less risk to users.
+
+### How can users be sure that the contract owner will not change certain conditions (via an update)?
+
+The contract must be verified, this allows you to check the source code and ensure that there is no update logic to ensure it remains unchanged. If the contract does indeed lack mechanisms to change the code, the terms of the contract will remain unchanged after deployment.
+
+Sometimes the logic for updating may exist, but the rights to change the code may be moved to an "empty" address, which also precludes changes.
+
### Is it possible to re-deploy code to an existing address or does it have to be deployed as a new contract?
Yes, this is possible. If a smart contract carries out specific instructions (`set_code()`) its code can be updated and the address will remain the same.
diff --git a/docs/develop/howto/fees-low-level.md b/docs/develop/howto/fees-low-level.md
index 0f43d1ead7..a3cebfac59 100644
--- a/docs/develop/howto/fees-low-level.md
+++ b/docs/develop/howto/fees-low-level.md
@@ -4,35 +4,124 @@
This section describes instructions and manuals for interacting with TON at a low level.
:::
+:::caution
+Here you will find the **raw formulas** for calculating commissions and fees on TON.
+
+However, most of them are **already implemented through opcodes**! So, you **use them instead of manual calculations**.
+:::
+
This document provides a general idea of transaction fees on TON and particularly computation fees for the FunC code. There is also a [detailed specification in the TVM whitepaper](https://ton.org/tvm.pdf).
## Transactions and phases
-As was described in the [TVM overview](/learn/tvm-instructions/tvm-overview), transaction execution consists of a few phases. During those phases, the corresponding fees may be deducted.
+As was described in the [TVM overview](/learn/tvm-instructions/tvm-overview), transaction execution consists of a few phases. During those phases, the corresponding fees may be deducted. There is a [high-level fees overview](/develop/smart-contracts/fees).
+
+## Storage fee
+
+TON validators collect storage fees from smart contracts.
+
+Storage fees are collected from the smart contract balance at the **Storage phase** of any transaction due storage payments for the account state
+(including smart-contract code and data, if present) up to the present time. The smart contract may be frozen as a result.
+
+It’s important to keep in mind that on TON you pay for both the execution of a smart contract and for the **used storage** (check [@thedailyton article](https://telegra.ph/Commissions-on-TON-07-22)). `storage fee` depends on you contract size: number of cells and sum of number of bits from that cells. **Only unique hash cells are counted for storage and fwd fees i.e. 3 identical hash cells are counted as one**. It means you have to pay a storage fee for having TON Wallet (even if it's very-very small).
+
+If you have not used your TON Wallet for a significant period of time (1 year), _you will have to pay a significantly larger commission than usual because the wallet pays commission on sending and receiving transactions_.
+
+### Formula
+
+You can approximately calculate storage fees for smart contracts using this formula:
-Generally:
```cpp
-transaction_fee = storage_fees
- + in_fwd_fees
- + computation_fees
- + action_fees
- + out_fwd_fees
+ storage_fee = (cells_count * cell_price + bits_count * bit_price)
+ * time_delta / 2^16
```
-where:
- * `storage_fees`—fees corresponding to occupation of some space in chain state by contract
- * `in_fwd_fees`—fees for importing to blockchain incoming message (it is only relevant for messages which were not previously on-chain, that is, `external` messages. For ordinary messages from contract to contract this fee is not applicable)
- * `computation_fees`—fees corresponding to execution of TVM instructions
- * `action_fees`—fees related to processing of action list (sending messages, setting libraries etc.)
- * `out_fwd_fees`—fees related to importing to blockchain of outcoming message
+
+Let's examine each value more closely:
+
+* `storage_fee`—price for storage for `time_delta` seconds
+* `cells_count`—count of cells used by smart contract
+* `bits_count`—count of bits used by smart contract
+* `cell_price`—price of single cell
+* `bit_price`—price of single bit
+
+Both `cell_price` and `bit_price` could be obtained from Network Config [param 18](/develop/howto/blockchain-configs#param-18).
+
+Current values are:
+
+* Workchain.
+ ```cpp
+ bit_price_ps:1
+ cell_price_ps:500
+ ```
+* Masterchain.
+ ```cpp
+ mc_bit_price_ps:1000
+ mc_cell_price_ps:500000
+ ```
+
+### Calculator Example
+
+You can use this JS script to calculate storage price for 1 MB in the workchain for 1 year
+
+```js live
+
+// Welcome to LIVE editor!
+// feel free to change any variables
+// Source code uses RoundUp for the fee amount, so does the calculator
+
+function storageFeeCalculator() {
+
+ const size = 1024 * 1024 * 8 // 1MB in bits
+ const duration = 60 * 60 * 24 * 365 // 1 Year in secs
+
+ const bit_price_ps = 1
+ const cell_price_ps = 500
+
+ const pricePerSec = size * bit_price_ps +
+ + Math.ceil(size / 1023) * cell_price_ps
+
+ let fee = Math.ceil(pricePerSec * duration / 2**16) * 10**-9
+ let mb = (size / 1024 / 1024 / 8).toFixed(2)
+ let days = Math.floor(duration / (3600 * 24))
+
+ let str = `Storage Fee: ${fee} TON (${mb} MB for ${days} days)`
+
+ return str
+}
+
+
+```
+
+## Forward fees
+
+Internal messages define an `ihr_fee` in Toncoins, which is subtracted from the value attached to the message and awarded to the validators of the destination shardchain if they include the message by the IHR mechanism. The `fwd_fee` is the original total forwarding fee paid for using the HR mechanism; it is automatically computed from some configuration parameters and the size of the message at the time the message is generated. Notice that the total value carried by a newly-created internal outbound message equals the sum of value, `ihr_fee`, and `fwd_fee`. This sum is deducted from the balance of the source account. Of these components, only value is always credited to the destination account on message delivery. The `fwd_fee` is collected by the validators on the HR path from the source to the destination, and the `ihr_fee` is either collected by the validators of the destination shardchain (if the message is delivered via IHR), or credited to the destination account.
+
+:::info
+`fwd_fee` covers 2/3 of the cost, as 1/3 is allocated to the `action_fee` when the message is created.
+
+```cpp
+auto fwd_fee_mine = msg_prices.get_first_part(fwd_fee);
+auto fwd_fee_remain = fwd_fee - fwd_fee_mine;
+
+fees_total = fwd_fee + ihr_fee;
+fees_collected = fwd_fee_mine;
+
+ap.total_action_fees += fees_collected;
+ap.total_fwd_fees += fees_total;
+```
+
+:::
## Computation fees
### Gas
-All computation costs are nominated in gas units. The price of gas units is determined by this chain config (Config 20 for masterchain and Config 21 for basechain) and may be changed only by consensus of the validator. Note that unlike in other systems, the user cannot set his own gas price, and there is no fee market.
-Current settings in basechain are as follows: 1 unit of gas costs 1000 nanotons.
+All computation costs are nominated in gas units. The price of gas units is determined by this [chain config](/develop/howto/blockchain-configs#param-20) (Config 20 for masterchain and Config 21 for basechain) and may be changed only by consensus of validators. Note that unlike in other systems, the user cannot set his own gas price, and there is no fee market.
+
+Current settings in basechain are as follows: 1 unit of gas costs 400 nanotons.
+
+### TVM instructions cost
-## TVM instructions cost
On the lowest level (TVM instruction execution) the gas price for most primitives
equals the _basic gas price_, computed as `P_b := 10 + b + 5r`,
where `b` is the instruction length in bits and `r` is the
@@ -52,18 +141,20 @@ Apart from those basic fees, the following fees appear:
| Moving stack elements | **1** | Price for moving stack elements between continuations. It will charge correspond gas price for every element. However, the first 32 elements moving is free. |
-## FunC constructions gas fees
+### FunC constructions gas fees
-Almost all functions used in FunC are defined in [stdlib.func](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/stdlib.fc) which maps FunC functions to Fift assembler instructions. In turn, Fift assembler instructions are mapped to bit-sequence instructions in [asm.fif](https://github.com/ton-blockchain/ton/blob/master/crypto/fift/lib/Asm.fif). So if you want to understand how much exactly the instruction call will cost you, you need to find `asm` representation in `stdlib.func`, then find bit-sequence in `asm.fif` and calculate instruction length in bits.
+Almost all FunC functions used in this article are defined in [stablecoin stdlib.fc contract](https://github.com/ton-blockchain/stablecoin-contract) (actually, stdlib.fc with new opcodes is currently **under development** and **not yet presented on the mainnet repos**, but you can use `stdlib.fc` from [stablecoin](https://github.com/ton-blockchain/ton) source code as reference) which maps FunC functions to Fift assembler instructions. In turn, Fift assembler instructions are mapped to bit-sequence instructions in [asm.fif](https://github.com/ton-blockchain/ton/blob/master/crypto/fift/lib/Asm.fif). So if you want to understand how much exactly the instruction call will cost you, you need to find `asm` representation in `stdlib.fc`, then find bit-sequence in `asm.fif` and calculate instruction length in bits.
However, generally, fees related to bit-lengths are minor in comparison with fees related to cell parsing and creation, as well as jumps and just number of executed instructions.
So, if you try to optimize your code start with architecture optimization, the decreasing number of cell parsing/creation operations, and then with the decreasing number of jumps.
### Operations with cells
+
Just an example of how proper cell work may substantially decrease gas costs.
-Let''s imagine that you want to add some encoded payload to the outgoing message. Straightforward implementation will be as follows:
+Let's imagine that you want to add some encoded payload to the outgoing message. Straightforward implementation will be as follows:
+
```cpp
slice payload_encoding(int a, int b, int c) {
return
@@ -79,7 +170,7 @@ slice payload_encoding(int a, int b, int c) {
.store_uint(0x18, 6)
.store_slice(destination)
.store_coins(0)
- .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1) ;; some flags related to message header
+ .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1) ;; default message headers (see sending messages page)
.store_uint(0x33bbff77, 32) ;; op-code (see smart-contract guidelines)
.store_uint(cur_lt(), 64) ;; query_id (see smart-contract guidelines)
.store_slice(payload)
@@ -107,7 +198,7 @@ builder payload_encoding(int a, int b, int c) {
.store_uint(0x18, 6)
.store_slice(destination)
.store_coins(0)
- .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1) ;; some flags related to message header
+ .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1) ;; default message headers (see sending messages page)
.store_uint(0x33bbff77, 32) ;; op-code (see smart-contract guidelines)
.store_uint(cur_lt(), 64) ;; query_id (see smart-contract guidelines)
.store_builder(payload)
@@ -115,38 +206,58 @@ builder payload_encoding(int a, int b, int c) {
send_raw_message(msg, 64);
}
```
+
By passing bit-string in the another form (builder instead of slice) we substantially decrease computation cost by very slight change in code.
### Inline and inline_refs
+
By default, when you have a FunC function, it gets its own `id`, stored in a separate leaf of id->function dictionary, and when you call it somewhere in the program, a search of the function in dictionary and subsequent jump occur. Such behavior is justified if your function is called from many places in the code and thus jumps allow to decrease the code size (by storing a function body once). However, if the function is only used once or twice, it is often much cheaper to declare this function as `inline` or `inline_ref`. `inline` modificator places the body of the function right into the code of the parent function, while `inline_ref` places the function code into the reference (jumping to the reference is still much cheaper than searching and jumping to the dictionary entry).
### Dictionaries
+
Dictionaries on TON are introduced as trees (DAGs to be precise) of cells. That means that if you search, read, or write to the dictionary, you need to parse all cells of the corresponding branch of the tree. That means that
* a) dicts operations are not fixed in gas costs (since the size and number of nodes in the branch depend on the given dictionary and key)
* b) it is expedient to optimize dict usage by using special instructions like `replace` instead of `delete` and `add`
* c) developer should be aware of iteration operations (like next and prev) as well `min_key`/`max_key` operations to avoid unnecessary iteration through the whole dict
### Stack operations
+
Note that FunC manipulates stack entries under the hood. That means that the code:
+
```cpp
(int a, int b, int c) = some_f();
return (c, b, a);
```
+
will be translated into a few instructions which changes the order of elements on the stack.
When the number of stack entries is substantial (10+), and they are actively used in different orders, stack operations fees may become non-negligible.
-## Fee's calculation Formulas
+## Action fee
+
+Action fee is deducted from the balance of the source account during processing action list which is perfomed after Computing phase.
+These are the actions that lead to pay fees:
+
+* `SENDRAWMSG` sends a raw message.
+* `RAWRESERVE` creates an output action which would reserve N Nanotons.
+* `RAWRESERVEX` similar to `RAWRESERVE`, but also accepts a dictionary with extra currencies.
+* `SETCODE` creates an output action that would change this smart contract code.
+* `SETLIBCODE` creates an output action that would modify the collection of this smart contract libraries by adding or removing library with given code.
+* `CHANGELIB` creates an output action similarly to `SETLIBCODE`, but instead of the library code accepts its hash.
+* `FB08–FB3F` reserved for output action primitives.
+
+## Fee's calculation formulas
### storage_fees
+
```cpp
storage_fees = ceil(
(account.bits * bit_price
+ account.cells * cell_price)
* period / 2 ^ 16)
```
-### in_fwd_fees, out_fwd_fees
+### in_fwd_fees, out_fwd_fees
```cpp
msg_fwd_fees = (lump_price
+ ceil(
@@ -155,25 +266,45 @@ msg_fwd_fees = (lump_price
ihr_fwd_fees = ceil((msg_fwd_fees * ihr_price_factor) / 2^16)
```
+
+:::info
+Only unique hash cells are counted for storage and fwd fees i.e. 3 identical hash cells are counted as one.
+
+In particular, it deduplicates data: if there are several equivalent sub-cells referenced in different branches, their content is only stored once.
+
+Read more about [deduplication](/develop/data-formats/library-cells).
+:::
+
// bits in the root cell of a message are not included in msg.bits (lump_price pays for them)
### action_fees
+
```cpp
action_fees = sum(out_ext_msg_fwd_fee) + sum(int_msg_mine_fee)
```
-### Config file
+## Fee's config file
-All fees are nominated for a certain gas amount and may be changed. The config file represents the current fee cost.
+All fees are nominated in nanotons or nanotons multiplied by 2^16 to [maintain accuracy while using integer](/develop/howto/fees-low-level#forward-fees) and may be changed. The config file represents the current fee cost.
-* storage_fees = [p18](https://explorer.toncoin.org/config?workchain=-1&shard=8000000000000000&seqno=22185244&roothash=165D55B3CFFC4043BFC43F81C1A3F2C41B69B33D6615D46FBFD2036256756382&filehash=69C43394D872B02C334B75F59464B2848CD4E23031C03CA7F3B1F98E8A13EE05#configparam18)
-* in_fwd_fees = [p24](https://explorer.toncoin.org/config?workchain=-1&shard=8000000000000000&seqno=22185244&roothash=165D55B3CFFC4043BFC43F81C1A3F2C41B69B33D6615D46FBFD2036256756382&filehash=69C43394D872B02C334B75F59464B2848CD4E23031C03CA7F3B1F98E8A13EE05#configparam24), [p25](https://explorer.toncoin.org/config?workchain=-1&shard=8000000000000000&seqno=22185244&roothash=165D55B3CFFC4043BFC43F81C1A3F2C41B69B33D6615D46FBFD2036256756382&filehash=69C43394D872B02C334B75F59464B2848CD4E23031C03CA7F3B1F98E8A13EE05#configparam25)
-* computation_fees = [p20](https://explorer.toncoin.org/config?workchain=-1&shard=8000000000000000&seqno=22185244&roothash=165D55B3CFFC4043BFC43F81C1A3F2C41B69B33D6615D46FBFD2036256756382&filehash=69C43394D872B02C334B75F59464B2848CD4E23031C03CA7F3B1F98E8A13EE05#configparam20), [p21](https://explorer.toncoin.org/config?workchain=-1&shard=8000000000000000&seqno=22185244&roothash=165D55B3CFFC4043BFC43F81C1A3F2C41B69B33D6615D46FBFD2036256756382&filehash=69C43394D872B02C334B75F59464B2848CD4E23031C03CA7F3B1F98E8A13EE05#configparam21)
-* action_fees = [p24](https://explorer.toncoin.org/config?workchain=-1&shard=8000000000000000&seqno=22185244&roothash=165D55B3CFFC4043BFC43F81C1A3F2C41B69B33D6615D46FBFD2036256756382&filehash=69C43394D872B02C334B75F59464B2848CD4E23031C03CA7F3B1F98E8A13EE05#configparam24), [p25](https://explorer.toncoin.org/config?workchain=-1&shard=8000000000000000&seqno=22185244&roothash=165D55B3CFFC4043BFC43F81C1A3F2C41B69B33D6615D46FBFD2036256756382&filehash=69C43394D872B02C334B75F59464B2848CD4E23031C03CA7F3B1F98E8A13EE05#configparam25)
-* out_fwd_fees = [p24](https://explorer.toncoin.org/config?workchain=-1&shard=8000000000000000&seqno=22185244&roothash=165D55B3CFFC4043BFC43F81C1A3F2C41B69B33D6615D46FBFD2036256756382&filehash=69C43394D872B02C334B75F59464B2848CD4E23031C03CA7F3B1F98E8A13EE05#configparam24), [p25](https://explorer.toncoin.org/config?workchain=-1&shard=8000000000000000&seqno=22185244&roothash=165D55B3CFFC4043BFC43F81C1A3F2C41B69B33D6615D46FBFD2036256756382&filehash=69C43394D872B02C334B75F59464B2848CD4E23031C03CA7F3B1F98E8A13EE05#configparam25)
+* storage_fees = [p18](https://tonviewer.com/config#18)
+* in_fwd_fees = [p24](https://tonviewer.com/config#24), [p25](https://tonviewer.com/config#25)
+* computation_fees = [p20](https://tonviewer.com/config#20), [p21](https://tonviewer.com/config#21)
+* action_fees = [p24](https://tonviewer.com/config#24), [p25](https://tonviewer.com/config#25)
+* out_fwd_fees = [p24](https://tonviewer.com/config#24), [p25](https://tonviewer.com/config#25)
:::info
-[A direct link to the mainnet config file](https://explorer.toncoin.org/config?workchain=-1&shard=8000000000000000&seqno=22185244&roothash=165D55B3CFFC4043BFC43F81C1A3F2C41B69B33D6615D46FBFD2036256756382&filehash=69C43394D872B02C334B75F59464B2848CD4E23031C03CA7F3B1F98E8A13EE05)
+[A direct link to the mainnet live config file](https://tonviewer.com/config)
+
+For educational purposes [example of the old one](https://explorer.toncoin.org/config?workchain=-1&shard=8000000000000000&seqno=22185244&roothash=165D55B3CFFC4043BFC43F81C1A3F2C41B69B33D6615D46FBFD2036256756382&filehash=69C43394D872B02C334B75F59464B2848CD4E23031C03CA7F3B1F98E8A13EE05)
:::
-*Based on @thedailyton [article](https://telegra.ph/Fees-calculation-on-the-TON-Blockchain-07-24) from 24.07*
\ No newline at end of file
+## References
+
+* Based on @thedailyton [article](https://telegra.ph/Fees-calculation-on-the-TON-Blockchain-07-24) from 24.07*
+
+## See Also
+
+* [TON Fees overview](/develop/smart-contracts/fees)
+* [Transactions and Phases](/learn/tvm-instructions/tvm-overview#transactions-and-phases)
+* [Fees calculation](/develop/smart-contracts/fee-calculation)
\ No newline at end of file
diff --git a/docs/develop/howto/network-configs.md b/docs/develop/howto/network-configs.md
index 802ea95e91..c9eefd1d64 100644
--- a/docs/develop/howto/network-configs.md
+++ b/docs/develop/howto/network-configs.md
@@ -1,10 +1,11 @@
# Network Configs
-:::info
-This page is currently under development. You can suggest something or make a contribution in the corresponding [Footstep #127](https://github.com/ton-society/ton-footsteps/issues/127).
-:::
-
On this page you can find active network configs of TON Blockchain:
- Mainnet: https://ton.org/global-config.json
- Testnet: https://ton.org/testnet-global.config.json
+
+## See Also
+
+- [Node Types](https://docs.ton.org/participate/nodes/node-types)
+- [Blockchain Params Config](/develop/howto/blockchain-configs)
\ No newline at end of file
diff --git a/docs/develop/network/adnl-tcp.md b/docs/develop/network/adnl-tcp.md
index 7b8dd367c7..58375a689a 100644
--- a/docs/develop/network/adnl-tcp.md
+++ b/docs/develop/network/adnl-tcp.md
@@ -89,12 +89,12 @@ We are looking for the [TL schema we need](https://github.com/ton-blockchain/ton
* 32 bytes nonce -> random 32 bytes
* 4 bytes of ID ADNLQuery schema -> **7af98bb4**
* 32 bytes `query_id:int256` -> random 32 bytes
-* * 1 byte array size -> **12**
-* * 4 byte of ID LiteQuery schema -> **df068c79**
-* * * 1 byte array size -> **4**
-* * * 4 bytes of ID getMasterchainInfo schema -> **2ee6b589**
-* * * 3 zero bytes of padding (alignment to 8)
-* * 3 zero bytes of padding (alignment to 16)
+ * 1 byte array size -> **12**
+ * 4 byte of ID LiteQuery schema -> **df068c79**
+ * 1 byte array size -> **4**
+ * 4 bytes of ID getMasterchainInfo schema -> **2ee6b589**
+ * 3 zero bytes of padding (alignment to 8)
+ * 3 zero bytes of padding (alignment to 16)
* 32 bytes of checksum SHA256 from nonce and payload
Packet example in hex:
diff --git a/docs/develop/oracles/about_blockchain_oracles.md b/docs/develop/oracles/about_blockchain_oracles.md
new file mode 100644
index 0000000000..ffd9a724b6
--- /dev/null
+++ b/docs/develop/oracles/about_blockchain_oracles.md
@@ -0,0 +1,60 @@
+# About Oracles
+
+Blockchain oracles are entities that connect the blockchain to external systems, allowing smart contracts to be executed based on real-world inputs.
+
+## How blockchain oracles work
+
+Blockchain oracles are specialized services that act as bridges between the real world and blockchain technology. They provide smart contracts with relevant and necessary information from the outside world, such as exchange rates, payment statuses or even weather conditions. This data helps to automate and fulfill the terms of contracts without direct human intervention.
+
+The basic principle behind oracles is their ability to function outside of the blockchain by connecting to various online sources to collect data. Although oracles are not part of the blockchain itself, they play a key role in making it functional by acting as a trusted intermediary that reliably feeds external data into the system.
+
+Most oracles tend to be decentralized, avoiding the risks associated with dependence on a single source of data. This provides greater security and reliability to the system as data is verified and validated through a network of nodes before it is used in smart contracts. This approach minimizes the risk of manipulation and errors, ensuring that the information provided is accurate and up-to-date.
+
+## Varieties of blockchain oracles
+
+Blockchain oracles are categorized according to various aspects: mechanism of operation, data sources, data direction, and governance structure. Let's take a look at the most common types of oracles.
+
+### Software and hardware oracles
+
+Software oracles work with online data that is stored in various digital sources such as databases, servers, cloud storage. Hardware oracles connect the physical world to the digital world, using sensors and scanners to transfer data about real-world events to the blockchain.
+
+### Incoming and outgoing oracles
+
+Inbound oracles feed information into the blockchain, such as weather data for insurance contracts. Outbound oracles, in turn, send data from the blockchain to the outside world, such as transaction notifications. Using both types of oracles improves the overall reliability of the system by ensuring a continuous and accurate flow of data in both directions. It also reduces the likelihood of a single point of failure problem by diversifying the sources and destinations of critical data, reducing the risk that a failure in one component could jeopardize the entire system.
+
+### Centralized and decentralized oracles
+
+Centralized oracles are controlled by a single party, which creates security and reliability risks. Decentralized oracles use multiple nodes to verify data, making them more secure and reliable.
+
+### Oracles for specific smart-contracts
+
+These oracles are developed individually for certain smart contracts and may not be as popular due to their specificity and high development costs.
+
+### Crosschain oracles
+
+These oracles are used to transfer data between different blockchains and are a critical component of bridges. They are used for decentralized applications that use cross-chain transactions, such as cross-chain transfer of cryptoassets from one network to another.
+
+## Application of blockchain oracles
+
+Blockchain oracles build bridges between the digital world of blockchains and real life, opening up a wide range of applications. Let's take a look at some of the most popular uses of oracles.
+
+### DeFi (decentralized finance)
+
+Oracles play a critical role in the DeFi ecosystem by providing market price and cryptocurrency data. Price oracles allow DeFi platforms to link token values to real assets, which is essential for controlling liquidity and securing users' positions. Additionally, oracles are vital for lending platforms, where accurate price data ensures proper collateral valuation and risk management, safeguarding both lenders and borrowers. This makes transactions more transparent and secure, contributing to the stability and reliability of financial transactions.
+
+### Insurance
+
+Oracles can automatically read and analyze data from a variety of sources to determine the occurrence of insurance events. This allows insurance contracts to pay claims automatically, reducing the need to manually process each case and speeding up response times to insurance events.
+
+### Logistics
+
+The use of oracles in logistics allows smart contracts to automatically perform payments and other actions based on data received from barcode scanners or sensors on vehicles. This improves delivery accuracy and efficiency by minimizing errors and delays.
+
+### Random number generation
+
+It is difficult to generate random numbers in smart contracts because all operations must be reproducible and predictable, which contradicts the concept of randomness. Computational oracles solve this problem by bringing data from the outside world into contracts. They can generate verifiable random numbers for games and lotteries, ensuring fairness and transparency of results.
+
+## List of oracles in TON
+
+* [RedStone Oracles](/develop/oracles/red_stone)
+
diff --git a/docs/develop/oracles/red_stone.mdx b/docs/develop/oracles/red_stone.mdx
new file mode 100644
index 0000000000..915eab006f
--- /dev/null
+++ b/docs/develop/oracles/red_stone.mdx
@@ -0,0 +1,351 @@
+import ThemedImage from '@theme/ThemedImage';
+
+# RedStone Oracles
+
+## How RedStone oracles work with TON
+
+RedStone oracles use an alternative design of providing oracle data to smart contracts. Instead of constantly persisting data on the contract's storage (by data providers), the information is brought on-chain only when needed (by end users). Until that moment data remains in the decentralised cache layer, which is powered by RedStone light cache gateways and
+streams data broadcasting protocol. Data is transferred to the contract by end users, who should attach signed data
+packages to their function invocations. The information integrity is verified on-chain through signature checking.
+
+To learn more about RedStone oracles design go to the [RedStone docs](https://docs.redstone.finance/docs/introduction)
+
+## Documentation links
+
+* [Redstone TON Connector](https://github.com/redstone-finance/redstone-oracles-monorepo/tree/main/packages/ton-connector)
+
+## Smart Contracts
+
+### price_manager.fc
+
+- Sample oracle contract that consumes RedStone oracles data [price_manager.fc](https://github.com/redstone-finance/redstone-oracles-monorepo/blob/main/packages/ton-connector/contracts/price_manager.fc) written in
+ FunC. It requires [TVM Upgrade 2023.07](https://docs.ton.org/learn/tvm-instructions/tvm-upgrade-2023-07).
+
+#### initial data
+
+As mentioned above, the data packages transferred to the contract are being verified by signature checking.
+To be counted to achieve the `signer_count_threshold`, the signer signing the passed data
+should be one of the `signers` passed in the initial data. There is also needed `signer_count_threshold` to be
+passed.
+
+Due to the architecture of TON contracts, the initial data must convene with the contract's storage structure,
+which is constructed as below:
+
+```ts
+ begin_cell()
+ .store_uint(signer_count_threshold, 8) /// number as passed below
+ .store_uint(timestamp, TIMESTAMP_BITS) /// initially 0 representing the epoch 0
+ .store_ref(signers) /// serialized tuple of values passed below
+ .end_cell();
+```
+
+The value of `signers` should be passed as a serialized `tuple` of `int`s.
+See [tuple](https://github.com/ton-core/ton-core/blob/main/src/tuple/tuple.ts).
+
+
+
+In the function parameters below, each `feed_id` is a string encoded to `int` which means, that's a value
+consisting of hex-values of the particular letters in the string. For example:
+`'ETH'` as an `int` is `0x455448` in hex or `4543560` in decimal, as `256*256*ord('E')+256*ord('T')+ord('H')`.
+
+You can use: `feed_id=hexlify(toUtf8Bytes(feed_string))` to convert particular values or
+the [endpoint](https://cairo-utils-web.vercel.app/)
+
+The value of `feed_ids` should be passed as a serialized `tuple` of `int`s.
+
+The value `payload` is packed from an array of bytes representing the serialized RedStone payload.
+See [TON RedStone payload packing](#-ton-redstone-payload-packing) section below, as well as the file [constants.fc](https://github.com/redstone-finance/redstone-oracles-monorepo/blob/main/packages/ton-connector/contracts/redstone/constants.fc), containing all needed `int`-length constants.
+
+#### get_prices
+
+```func
+(cell) get_prices_v2(cell data_feed_ids, cell payload) method_id;
+```
+
+The function process on-chain the `payload` passed as an argument
+and returns a `cell` of aggregated values of each feed passed as an identifier inside `feed_ids`.
+
+Due to HTTP GET method length limitation in TON API v4, the function is written for TON API v2.
+
+That are just a `method_id` functions - they don't modify the contract's storage and don't consume TONs.
+
+#### OP_REDSTONE_WRITE_PRICES
+
+Regardless of the on-fly processing, there also exists a method for processing the `payload` on-chain, but
+saving/writing the aggregated values to the contract's storage. The values persist in the contract's storage and then can be read by using `read_prices` function. The timestamp of data last saved/written to the contract is able to read by using the `read_timestamp` function.
+
+The method must be invoked as a TON internal message. The arguments of the message are:
+
+- an `int` representing RedStone_Write_Prices name hashed by keccak256 as defined
+ in [constants.ts](https://github.com/redstone-finance/redstone-oracles-monorepo/blob/main/packages/ton-connector/src/config/constants.ts)
+- a `cell` - ref representing the `data_feed_ids` as a serialized `tuple` of `int`s.\
+- a `cell` - ref representing the packed RedStone payload
+
+```func
+ int op = in_msg_body~load_uint(OP_NUMBER_BITS);
+
+ if (op == OP_REDSTONE_WRITE_PRICES) {
+ cell data_feeds_cell = in_msg_body~load_ref();
+ cell payload_cell = in_msg_body~load_ref();
+
+ // ...
+ }
+```
+
+That's an internal message - it consumes GAS and modifies the contract's storage, so must be paid by TONs.
+
+See how it works on: https://ton-showroom.redstone.finance/
+
+#### read_prices
+
+```func
+(tuple) read_prices(tuple data_feed_ids) method_id;
+```
+
+The function reads the values persisting in the contract's storage and returns a tuple corresponding to the
+passed `feed_ids`.
+The function doesn't modify the storage and can read only aggregated values of the `feed_ids` saved by
+using `write_prices` function.
+
+That's just a `method_id` function - it doesn't modify the contract's storage and don't consume TONs.
+
+#### read_timestamp
+
+```func
+(int) read_timestamp() method_id;
+```
+
+Returns the timestamp of data last saved/written to the contract's storage by using `OP_REDSTONE_WRITE_PRICES` message.
+
+That's just a `method_id` function - it doesn't modify the contract's storage and don't consume TONs.
+
+### price_feed.fc
+
+Due to the architecture of TON contracts, the initial data must convene with the contract's storage structure,
+which is constructed as below:
+
+```ts
+beginCell()
+ .storeUint(BigInt(hexlify(toUtf8Bytes(this.feedId))), consts.DATA_FEED_ID_BS * 8)
+ .storeAddress(Address.parse(this.managerAddress))
+ .storeUint(0, consts.DEFAULT_NUM_VALUE_BS * 8) /// initially 0 representing the epoch 0
+ .storeUint(0, consts.TIMESTAMP_BS * 8)
+ .endCell();
+```
+
+To define the initial (storage) data for the Price feed contract, use the predefined
+class [PriceFeedInitData.ts](https://github.com/redstone-finance/redstone-oracles-monorepo/blob/main/packages/ton-connector/src/price-feed/PriceFeedInitData.ts).
+
+#### OP_REDSTONE_FETCH_DATA
+
+Regardless of reading the values persisting in the contract's from outside the network,
+there is a possibility for fetching the value stored in the contract for a `feed_id` on-chain directly.
+There must be invoked an internal message `OP_REDSTONE_FETCH_DATA`. The arguments of the message are:
+
+* an `int` representing `RedStone_Fetch_Data` name hashed by keccak256 as defined
+ in [constants.ts](https://github.com/redstone-finance/redstone-oracles-monorepo/blob/main/packages/ton-connector/src/config/constants.ts)
+* an `int` representing the `feed_id` value.
+* a `slice` representing the `initial_sender` of the message, to allow they carried the remaining transaction balance
+ when the returning transaction goes.
+
+```func
+ int op = in_msg_body~load_uint(OP_NUMBER_BITS);
+
+ if (op == OP_REDSTONE_FETCH_DATA) {
+ int feed_id = in_msg_body~load_uint(DATA_FEED_ID_BITS);
+ cell initial_payload = in_msg_body~load_ref();
+
+ // ...
+ }
+```
+
+The returning message `OP_REDSTONE_DATA_FETCHED` message is sent to the sender, containing the `value` and
+the `timestamp` of the value has saved. The message can be then fetched in the sender and processed or saved in the
+sender's storage.
+The initial payload's `ref` (`initial_payload`) is added as a ref - containing for example the first message's sender,
+to allow they carry the remaining transaction balance.
+
+```ts
+begin_cell()
+ .store_uint(value, MAX_VALUE_SIZE_BITS)
+ .store_uint(timestamp, TIMESTAMP_BITS)
+ .store_ref(initial_payload)
+ .end_cell()
+```
+
+That's an internal message - it consumes GAS and modifies the contract's storage, so must be paid by TONs.
+
+#### get_price_and_timestamp
+
+```func
+(int, int) get_price_and_timestamp() method_id;
+```
+
+Returns the value and timestamp of the last saved/written data to the adapter's storage by sending `OP_REDSTONE_FETCH_DATA` message and fetching the returned value of the `OP_REDSTONE_DATA_FETCHED` message.
+
+That's just a `method_id` function - it doesn't modify the contract's storage and don't consume TONs.
+
+### single_feed_man.fc
+
+#### initial data
+
+Similar to the `prices` and `price_feed` initial data. Due to the architecture of TON contracts, the initial data must convene with the contract's storage structure, which is constructed as below:
+
+```ts
+beginCell()
+ .storeUint(BigInt(hexlify(toUtf8Bytes(this.feedId))), consts.DATA_FEED_ID_BS * 8)
+ .storeUint(this.signerCountThreshold, SIGNER_COUNT_THRESHOLD_BITS)
+ .storeUint(0, consts.DEFAULT_NUM_VALUE_BS * 8)
+ .storeUint(0, consts.TIMESTAMP_BS * 8)
+ .storeRef(serializeTuple(createTupleItems(this.signers)))
+ .endCell();
+```
+
+To define the initial (storage) data for the Prices contract, use the predefined
+class [SingleFeedManInitData.ts](https://github.com/redstone-finance/redstone-oracles-monorepo/blob/main/packages/ton-connector/src/single-feed-man/SingleFeedManInitData.ts).
+
+A contract like `price_manager`, but supporting
+the single feed only, to omit the communication needs between feed and manager contracts.
+
+#### get_price
+
+```func
+(int, int) get_price(cell payload) method_id;
+```
+
+Similar to `get_prices`, but omitting the first (`data_feed_ids`) argument as have it configured during
+the initialization. Returns also the min timestamp of the passed data packages.
+
+#### read_price_and_timestamp
+
+```func
+(int, int) read_price_and_timestamp() method_id;
+```
+
+Works as the `get_price_and_timestamp` function.
+
+#### OP_REDSTONE_WRITE_PRICE
+
+Similar to `OP_REDSTONE_WRITE_PRICES`, but omitting the first (`data_feed_ids`) `cell`-ref as have it configured during the initialization.
+
+```func
+ int op = in_msg_body~load_uint(OP_NUMBER_BITS);
+
+ if (op == OP_REDSTONE_WRITE_PRICE) {
+ cell payload_cell = in_msg_body~load_ref();
+
+ // ...
+ }
+```
+
+### sample_consumer.fc
+
+A sample consumer for data stored in the `price_feed`. Works also with `single_feed_man`.
+The `price_feed` to be called needs to be passed.
+
+#### initial data
+
+Similar to the `price_feed` initial data. Due to the architecture of TON contracts, the initial data must convene with the contract's storage structure, which is constructed as below:
+
+```ts
+beginCell()
+ .storeAddress(Address.parse(this.feedAddress))
+ .endCell();
+```
+
+To define the initial (storage) data for the Prices contract, use the predefined
+class [SampleConsumerInitData.ts](https://github.com/redstone-finance/redstone-oracles-monorepo/blob/main/packages/ton-connector/src/sample-consumer/SampleConsumerInitData.ts).
+
+The contract calls the single feed.
+
+#### OP_REDSTONE_READ_DATA
+
+There is a possibility for fetching the value stored in the contract for a `feed_id` on-chain directly.
+There must be invoked an internal message `OP_REDSTONE_READ_DATA`. The arguments of the message are:
+
+* a `slice` representing the `initial_sender` of the message, to allow they carried the remaining transaction balance
+ when the returning transaction goes.
+
+```func
+ int op = in_msg_body~load_uint(OP_NUMBER_BITS);
+
+ if (op == OP_REDSTONE_READ_DATA) {
+ cell initial_payload = in_msg_body~load_ref();
+
+ // ...
+ }
+```
+
+The returning message `OP_REDSTONE_DATA_READ` message is sent to the sender, containing the `feed_id`, `value` and
+the `timestamp` of the value has saved. The message can be then fetched in the sender and processed or saved in the
+sender's storage.
+The initial payload's `ref` (`initial_payload`) is added as a ref - containing for example the first message's sender,
+to allow they carry the remaining transaction balance.
+
+```ts
+begin_cell()
+ .store_uint(value, MAX_VALUE_SIZE_BITS)
+ .store_uint(timestamp, TIMESTAMP_BITS)
+ .store_ref(initial_payload)
+ .end_cell()
+```
+
+That's an internal message - it consumes GAS and modifies the contract's storage, so must be paid by TONs.
+
+## TON RedStone Payload packing
+
+Due to limitations of the Bag-size in TON [see](/develop/data-formats/cell-boc),
+the RedStone payload data - represented as a hex string - needed to be passed to a contract in a more complex way.
+
+Having the RedStone payload as defined [here](https://docs.redstone.finance/img/payload.png),
+the data should be passed as a Cell built as follows.
+
+1. The main *payload* `cell` consists of:
+ 1. the metadata in the **data-level bits** consisting of the parts as on the image:
+
+ ![payload-metadata.png](../../../static/img/docs/oracles/red-stone/payload-metadata.png)
+ 1. a **ref** containing a `udict` indexed by consecutive natural numbers (beginning from 0) containing the list of **data_package** `cell`s.
+1. Each *data-package* `cell` consists of:
+ 1. the data package's signature in the **data-level bits**:
+
+ ![payload-metadata.png](../../../static/img/docs/oracles/red-stone/payload-metadata.png)
+ 1. one **ref** to a `cell` containing the data of the rest of the data package on its **data-level**:
+
+ ![payload-metadata.png](../../../static/img/docs/oracles/red-stone/data-package-data.png)
+
+#### Current implementation limitations
+
+* The RedStone payload must be fetched by explicitly defining data feeds,
+ which leads to **one data point** belonging to **one data package**.
+* The unsigned metadata size must not be exceeding `127 - (2 + 3 + 9) = 113` bytes.
+
+#### Helper
+
+The ```createPayloadCell``` method in the [create-payload-cell.ts](https://github.com/redstone-finance/redstone-oracles-monorepo/blob/main/packages/ton-connector/src/create-payload-cell.ts) file
+checks the limitations and prepares the data to be sent to the contract as described above.
+
+#### Sample serialization
+
+The image below contains data for `2` feeds times `2` unique signers:
+![payload-metadata.png](../../../static/img/docs/oracles/red-stone/sample-serialization.png)
+
+## Possible transaction failures
+
+* The number of signers recovered from the signatures matched with ```addresses``` passed in the initializer
+ must be greater or equal that the ```signer_count_threshold``` in the constructor, for each feed.
+ * Otherwise, it panics then with the `300` error, increased by the first index of the passed
+ feed which has broken the validation.
+* The timestamp of data-packages must be not older than 15 minutes in relation to the ```block_timestamp```.
+ * Otherwise, it panics then with the `200` error, increased by the first index of the payload's
+ data package which has broken the validation, increased additionally by `50` if the package's timestamp is too
+ future.
+* The internal messages consume gas and must be paid by TONs. The data are available on the contract
+ just after the transaction successes.
+* The other error codes are defined [here](https://github.com/redstone-finance/redstone-oracles-monorepo/blob/main/packages/ton-connector/src/config/constants.ts)
+
+## See Also
+
+- [Internal messages docs](/develop/smart-contracts/guidelines/internal-messages)
+- [RedStone data-packing](https://docs.redstone.finance/docs/smart-contract-devs/how-it-works)
+- [RedStone oracles smart-contracts](https://github.com/redstone-finance/redstone-oracles-monorepo/tree/main/packages/ton-connector/contracts)
diff --git a/docs/develop/overview.mdx b/docs/develop/overview.mdx
index 896616522a..b156e35327 100644
--- a/docs/develop/overview.mdx
+++ b/docs/develop/overview.mdx
@@ -1,54 +1,168 @@
import Button from '@site/src/components/button'
import Player from '@site/src/components/player'
-# Overview
+# TON Documentation
-Welcome to the TON documentation!
+Welcome to the official TON Blockchain development documentation!
-Whether you're a seasoned developer or new to the space, this page provides an introduction to the tools and resources you'll need to build on TON. Feel free to focus on the approach that suits the best for you.
+This resource aims to provide you with all the necessary information you'll need to build, test, and deploy applications on the TON Blockchain.
-- _Get Started with TON_ is a step-by-step guide to interacting with TON Blockchain and writing your first application. (video tutorial included)
-- _TON Hello World_ series provides detailed step-by-step guides to wallets, smart contracts, web apps, and testing & debugging smart contracts on TON.
+This is a collaborative open-source initiative, and contributions are always welcome. All documentation can be edited via GitHub, just [follow these instructions](/contribute).
-Get Started with TON
+- _TON Hello World_ series provides detailed step-by-step guides to wallets, smart contracts, mini apps, and testing & debugging smart contracts on TON.
+- _Get Started with TON_ is a step-by-step guide to interacting with TON Blockchain. (video tutorial included)
+
+
+````mdx-code-block
- TON Hello World
+ colorType="primary" sizeType={'sm'}>
+````
+TON Hello World
+````mdx-code-block
+
+````
+````mdx-code-block
+
+````
+Get Started with TON
+````mdx-code-block
+
+````
+
+### Blockchain Basics with TON
+
+This course introduces blockchain basics, with a special focus on practical skills in the TON ecosystem. You will understand how blockchain functions and its diverse applications.
+
+````mdx-code-block
+
+````
+Check Blockchain Basics Course
+````mdx-code-block
+
+````
+````mdx-code-block
+
+````
+CHN
+````mdx-code-block
+
+````
+````mdx-code-block
+
+````
+RU
+````mdx-code-block
+
+````
+
+### TON Course
+
+We're proud to present the __TON Blockchain Course__, which is a comprehensive guide to the TON Blockchain. The course is designed for developers who want to learn how to create smart contracts and decentralized applications on the TON Blockchain in engaging and interactive ways.
+
+It consists of __9 modules__ and covers the basics of the TON Blockchain, the FunC programming language, and the TON Virtual Machine (TVM).
+
+````mdx-code-block
+
+````
+Check TON Blockchain Course
+````mdx-code-block
+
+````
+````mdx-code-block
+
+````
+CHN
+````mdx-code-block
+
+````
+````mdx-code-block
+
+````
+RU
+````mdx-code-block
+````
-[//]: # (- [TON Hello World part 1: Step by step guide for working with your first TON wallet](https://ton-community.github.io/tutorials/01-wallet/))
+## Development Modules
-[//]: # (- [TON Onboarding Challenge: Mine your first Soulbound NFT on TON](/develop/get-started-with-ton))
+If you're new to TON Blockchain development, it's recommended that you start from the beginning and work your way through these topics.
-## Smart Contracts development
+### Foundational Concepts
+
+- [The Open Network](/learn/introduction) - A high-level overview of TON Blockchain.
+- [Blockchain of Blockchains](/learn/overviews/ton-blockchain) - a down-to-earth explanation of TON Blockchain.
+- [Smart Contract Addresses](/learn/overviews/addresses) - A detailed explanation of Addresses.
+- [Cells as a Data Structure](/learn/overviews/cells) - A high-level explanation of data structures.
+- [TON Networking](/learn/networking/overview) - A high-level overview of TON peer-to-peer protocols.
+- [TON Virtual Machine (TVM)](/learn/tvm-instructions/tvm-overview) - A high-level overview of TON Virtual Machine.
+- [Transactions and Phases](/learn/tvm-instructions/tvm-overview#transactions-and-phases) - A detailed explanation of transactions and phases.
+- [Transaction Fees](/develop/smart-contracts/fees) - A high-level explanation of transaction fees.
+
+### Infrastructure
+
+- [Node Types](/participate/nodes/node-types) - A detailed explanation of node types.
+- [Run a Full Node](/participate/run-nodes/full-node) - A detailed explanation of how to run a node.
+- [TON DNS & Sites](/participate/web3/dns) - A detailed explanation of TON DNS & Sites.
+- [TON Storage](/participate/ton-storage/storage-daemon) - A detailed explanation of TON Storage.
+
+### Additional Resources
+
+- [**FAQ**](/develop/howto/faq) - Frequently Asked Questions
+- [FunC Documentation](/develop/func/overview)
+- [Fift Documentation](/develop/fift/overview)
+
+## Smart Contracts Development
Smart contracts are the building blocks of decentralized applications (DApps) on TON Blockchain. If you're looking to develop your own dApps, it's essential to understand how smart contracts work.
-Blueprint
+````mdx-code-block
- Read more
+ colorType="primary" sizeType={'sm'}>
+````
+Getting Started
+````mdx-code-block
-
+````
+````mdx-code-block
+
+````
+Use Blueprint
+````mdx-code-block
+
+````
+
The following resources provide valuable information for TON smart contract development:
* [TON Hello World: Step-by-step guide for writing your first smart contract](https://ton-community.github.io/tutorials/02-contract/) - An accessible and concise explanation of the fundamentals with JS.
* [How to work with wallet smart contracts](/develop/smart-contracts/tutorials/wallet) - Detailed and careful explanations of smart contract basics with the use of JS and GO.
* [Learn Smart Contracts by examples](/develop/smart-contracts/examples) (FunC, Fift)
-
+* [Speed Run TON](/develop/smart-contracts/examples) - 6 interactive challenges and step-by-step tutorials to learn smart contracts development.
## DApp Development
Decentralized applications (DApps) are applications that run on a peer-to-peer network of computers rather than a single computer (TON Blockchain). They are similar to traditional web applications, but they are built on top of a blockchain network. This means that DApps are decentralized, meaning that no single entity controls them.
+````mdx-code-block
+
+````
+Getting Started
+````mdx-code-block
+
+````
### DeFi Development
-* [Off-chain Payments Processing](/develop/dapps/asset-processing) — examples and concepts
-* [TON Jetton processing](/develop/dapps/asset-processing/jettons) — examples and concepts
-* [TON Connect](/develop/dapps/ton-connect/) — integration and authentication for applications
+* [TON Connect](/develop/dapps/ton-connect/overview) — integration and authentication for DApps.
+* [Off-chain Payments Processing](/develop/dapps/asset-processing) — examples and concepts for processing payments.
+* [TON Jetton processing](/develop/dapps/asset-processing/jettons) — examples and concepts for processing Jettons.
* [Fungible (FT) / Non-fungible (NFT) tokens](/develop/dapps/defi/tokens) — smart contracts, examples, tools
Take your first steps in DApps development with a comprehensive DApps building guide:
@@ -56,20 +170,10 @@ Take your first steps in DApps development with a comprehensive DApps building g
- [TON Hello World: Step by step guide for building your first web client](https://ton-community.github.io/tutorials/03-client/)
- [Telegram bot integration via TON Connect](/develop/dapps/ton-connect/tg-bot-integration)
-
-### SDKs and Examples
+### APIs and SDKs
* [APIs](/develop/dapps/apis)
* [SDKs](/develop/dapps/apis/sdk)
-* [Learn application development by examples](/develop/dapps/#examples)
-* [Learn smart contracts by examples](/develop/smart-contracts/examples)
-* [Telegram Web Apps (TWA) Development](https://docs.twa.dev/docs/introduction/about-platform)
-* [Authorization SDKs](/develop/dapps/ton-connect/developers)
-
-
-## TON Community Education Library
-
-- [Education](https://github.com/ton-community/awesome-ton#-education) - Unveil the comprehensive list of various educational materials, meticulously crafted by the remarkable TON Community.
## Frequently Asked Questions
diff --git a/docs/develop/smart-contracts/README.mdx b/docs/develop/smart-contracts/README.mdx
index 5a66f630c3..387f1837d9 100644
--- a/docs/develop/smart-contracts/README.mdx
+++ b/docs/develop/smart-contracts/README.mdx
@@ -1,162 +1,205 @@
import Button from '@site/src/components/button'
# Introduction
+
Smart contract creation, development, and deployment on TON Blockchain leverages the [FunC programming language](/develop/smart-contracts/#func-language) and [TON Virtual Machine (TVM)](/develop/smart-contracts/#ton-virtual-machine).
-## Quick Start
-Write and deploy your first smart contract with either *Blueprint* or *toncli* frameworks.
+## Quick Start: Your First Smart Contract
-### Blueprint
+Write and deploy your first smart contract with the *Blueprint* framework.
-Blueprint — is a development environment for writing, testing, and deploying smart contracts.
+Blueprint is a development environment for writing, testing, and deploying smart contracts.
To create a new demo project use the following command:
```bash
npm create ton@latest
```
-Learn Through Videos
-
- Learn More
-
-### toncli
-
-Toncli — is a TON cross-platform smart contract command line interface. Install this and run test project via following command:
-
-```bash
-toncli start wallet
-```
-
- Learn More
+````mdx-code-block
+
+````
+Read more
+````mdx-code-block
+
+````
+````mdx-code-block
+
+````
+TON Blockchain Course
+````mdx-code-block
+````
+````mdx-code-block
+
+````
+TON Speed Run Tutorials
+````mdx-code-block
+
+````
## Getting Started
-### Fast Track Tutorials
+### Fun and Easy Tutorials
-TON Hello World guide is _the easiest way_ to start with smart contracts development:
+Kickstart your journey with our beginner-friendly guide:
* [TON Hello World: Step-by-step guide for writing your first smart contract](https://ton-community.github.io/tutorials/02-contract/)
+* [TON Speed Run tutorials](https://tonspeedrun.com/)
+ - [🚩 Challenge 1: Simple NFT Deploy](https://github.com/romanovichim/TONQuest1)
+ - [🚩 Challenge 2: Chatbot Contract](https://github.com/romanovichim/TONQuest2)
+ - [🚩 Challenge 3: Jetton Vending Machine](https://github.com/romanovichim/TONQuest3)
+ - [🚩 Challenge 4: Lottery/Raffle](https://github.com/romanovichim/TONQuest4)
+ - [🚩 Challenge 5: Create UI to interact with the contract in 5 minutes](https://github.com/romanovichim/TONQuest5)
+ - [🚩 Challenge 6: Analyzing NFT sales on the Getgems marketplace](https://github.com/romanovichim/TONQuest6)
+
+### TON Course
+
+:::tip
+Before starting the course, make sure you have a good understanding of the basics of blockchain technology. If you have gaps in your knowledge, we recommend taking the [Blockchain Basics with TON](https://stepik.org/course/201294/promo) ([RU version](https://stepik.org/course/202221/), [CHN version](https://stepik.org/course/200976/)) course.
+:::
-### Comprehensive and Detailed Tutorials
-
-Detailed and cautionary explanations of smart contract basics:
-* [How to work with wallet smart contracts](/develop/smart-contracts/tutorials/wallet)
-
-
-## Smart Contract Guidelines
-
-Learn principals of designing and architecture of TON.
-
-TON’s systemized smart contract development allows engineers to build smart contracts for many uses. That said, to unlock the full capabilities of smart contract iteration on TON, it's necessary to follow our predetermined smart contract guidelines to ensure their correct composition.
-* [Smart contract guidelines](/develop/smart-contracts/guidelines)
-
-## TON Virtual Machine
-
-TON smart contracts are executed on TON Virtual Machine (TVM).
-The TVM is a stack-based virtual machine that employs many qualities that make it efficient and easy to implement.
+We're proud to present the __TON Blockchain Course__, which is a comprehensive guide to the TON Blockchain. The course is designed for developers who want to learn how to create smart contracts and decentralized applications on the TON Blockchain.
-To get a better understanding of how the TVM works, consider reading the TVM Overview section of our documentation.
+It consists of __9 modules__ and covers the basics of the TON Blockchain, smart contract development lifecycle, the FunC programming, and the TON Virtual Machine (TVM).
-TVM Overview
+````mdx-code-block
+
+````
+Check TON Course
+````mdx-code-block
+
+````
+````mdx-code-block
+
+````
+CHN
+````mdx-code-block
+
+````
+````mdx-code-block
+
+````
+RU
+````mdx-code-block
+
+````
+### Comprehensive Guides
-## Programming Languages
+For those who prefer detail and nuance, visit:
+* [How to work with wallet smart contracts](/develop/smart-contracts/tutorials/wallet)
-### FunC Language
-FunC is TON’s high-level programming language used to program smart contracts on TON Blockchain. The proprietary in-house language is a domain-specific statically typed framework which exhibits many characteristics simply not found in competing language types.
-FunC Overview
+## Examples of Smart Contracts
-### Fift language
+Explore ready-made smart contract examples and tools provided by the TON community.
-:::caution advanced level
-This information is **very low level** and may be challenging for newcomers to understand. Therefore, we suggest that you read about it later at your convenience.
+:::info little tip
+Feel free to focus on smart contracts written using _FunC_. Focusing on smart contracts written using FunC (*.fc) instead of the lower-level Fift (*.fif) language is often better.
:::
-Messages to smart contracts are binary data. To construct such messages, you can use one of the SDKs **or** the special programming language Fift.
+Standard examples of smart contracts on TON include wallets, electors (which manage validation on TON), and multi-signature wallets, which can be a reference when studying.
-Fift Overview
-
-### Tact language
+````mdx-code-block
+
+````
+Open Examples
+````mdx-code-block
+
+````
-:::caution
-The Tact language is developed by independent developers. Use at your own risk.
-:::
+## Smart Contract Best Practices
-Official Site
-
- Tact Hello World
-
+TON offers endless possibilities. Learn how to get the most out of them while adhering to recommended guidelines.
+* [Smart contract guidelines](/develop/smart-contracts/guidelines)
+## TON Virtual Machine (TVM)
+Discover the engine that runs your smart contracts.
+- [TVM Overview](/learn/tvm-instructions/tvm-overview)
-## Smart Contract Examples
-:::info little tip
-Feel free to focus on smart contracts written using _FunC_. it's often better to focus on smart contracts written using FunC (*.fc) instead of the lower-level Fift (*.fif) language.
-:::
-Standard examples of smart contracts on TON include wallets, electors (which manage validation on TON), multi-signature wallets can be a reference when studying.
+## Programming Languages
-If you're familiar with smart contracts, consider discover the following list:
+### 📘 FunC
-- [Fungible (Jettons), Non-Fungible (NFT), Semi-Fungible Tokens smart contracts](https://github.com/ton-blockchain/token-contract/tree/main)
-- [Getgems NFT, sale, auctions smart contracts (FunC)](https://github.com/getgems-io/nft-contracts)
-- [Wallet V4 smart contract example](https://github.com/ton-blockchain/wallet-contract)
-- [Standard smart contracts examples](https://github.com/ton-blockchain/ton/tree/master/crypto/smartcont)
-- [Super Simple Chatbot: doge.fc](https://github.com/LaDoger/doge.fc)
+The tailor-made language for TON smart contracts.
-Learn more examples on the [Examples of Smart Contracts](/develop/smart-contracts/examples) page.
+````mdx-code-block
+
+````
+FunC Overview
+````mdx-code-block
+
+````
-Additionally, discover more [FunC libraries and SDK](/develop/smart-contracts/libraries) in the FunC section of our documentation.
+### 📒 Tact
+The high-level language for TON smart contracts similar to TypeScript and Rust.
-## Environment
+:::caution
+Developed by the community. Use with caution.
+:::
-The installation process for Local Environments may require more knowledge and time, but they are better suited for everyday use and eliminate the need for internet dependency.
-These include IDE plugins, various SDKs, binaries, syntax highlighting, and more. Check out [our local environment installation guide](/develop/smart-contracts/environment/installation) to learn more.
+````mdx-code-block
+
+````
+Tact Official Site
+````mdx-code-block
+
+````
+````mdx-code-block
+
+````
+Tact Hello World
+````mdx-code-block
+
+````
-## Development Toolkit
-Development toolkits play a pivotal role in the development of smart contracts on TON Blockchain. To begin developing, testing, and debugging smart contracts on TON, we’ll make use of these products and services:
+### 📕 Fift (advanced)
-### SDKs
+:::caution advanced level
+Only for the brave!
+:::
-* [Blueprint](/develop/smart-contracts/sdk/javascript) - JS SDK for development and testing Smart Contracts.
-* [SDKs](/develop/dapps/apis/sdk) - The Open Network SDKs list for applications.
+````mdx-code-block
+
+````
+Fift Overview
+````mdx-code-block
+
+````
-### Other Tools
+## Community Tools
* [disintar/toncli](/develop/smart-contracts/sdk/toncli) — The toncli is the command line interface used to build, deploy, and test FunC contracts.
* [MyLocalTON](/participate/run-nodes/local-ton) — MyLocalTON is used to run a private TON Blockchain in your local environment.
-* [tonwhales.com/tools/boc](https://tonwhales.com/tools/boc) — BOC parser.
-* [tonwhales.com/tools/introspection-id](https://tonwhales.com/tools/introspection-id) — crc32 generator.
-* [@orbs-network/ton-access](https://www.orbs.com/ton-access/) — decentralized API gateway.
+* [tonwhales.com/tools/boc](https://tonwhales.com/tools/boc) — BOC parser
+* [tonwhales.com/tools/introspection-id](https://tonwhales.com/tools/introspection-id) — crc32 generator
+* [@orbs-network/ton-access](https://www.orbs.com/ton-access/) — decentralized API gateway
-## References
+## Further Reading
-Educational content from the TON community:
+Enhance your skillset with these community-driven educational resources.
-* [TON Learn FunC journey: 10 zero-to-hero lessons](https://blog.ton.org/func-journey) ([Ru version](https://github.com/romanovichim/TonFunClessons_ru))
-* [[YouTube] TON Dev Study [EN]](https://www.youtube.com/@TONDevStudy)
-* [[YouTube] TON Dev Study [RU]](https://www.youtube.com/@WikiMar)
-* [Introduction to FunC: how to start developing on TON?](https://dev.to/dvlkv/introduction-in-func-how-to-start-developing-in-ton-50hp)
-* [TON Hello World part 4: Step by step guide for testing your first smart contract](https://ton-community.github.io/tutorials/04-testing/)
+* [TON FunC Learning Path](https://blog.ton.org/func-journey) ([RU version](https://github.com/romanovichim/TonFunClessons_ru))
+* [YouTube Tutorials](https://www.youtube.com/@TONDevStudy) [[RU version]](https://www.youtube.com/@WikiMar)
-## See Also
+## Additional Resources
* [What is blockchain? What is a smart contract? What is gas?](https://blog.ton.org/what-is-blockchain)
-* [Payments processing](/develop/dapps/asset-processing)
-* [Transaction Fees](/develop/smart-contracts/fees#how-to-calculate-fees)
+* [Understanding Transaction Fees](/develop/smart-contracts/fees#how-to-calculate-fees)
diff --git a/docs/develop/smart-contracts/compile/README.md b/docs/develop/smart-contracts/compile/README.md
index a20dc834c7..8148b21f3c 100644
--- a/docs/develop/smart-contracts/compile/README.md
+++ b/docs/develop/smart-contracts/compile/README.md
@@ -1,7 +1,11 @@
-# Build and Compile
+# Compile and Build smart contracts on TON
Here is a list of libraries and repos to build your smart contract.
+**TLDR:**
+- In most cases, it's enough to use Blueprint SDK.
+- If you need more low-level approach, you can use ton-compiler or func-js.
+
## Blueprint
### Overview
@@ -75,7 +79,7 @@ FunC stdlib is bundled but could be disabled at runtime.
# Compile to binary form (for contract creation)
ton-compiler --input ./wallet.fc --output ./wallet.cell
-# Compile to fift (useful for debuging)
+# Compile to fift (useful for debugging)
ton-compiler --input ./wallet.fc --output-fift ./wallet.fif
# Compile to binary form and fift
diff --git a/docs/develop/smart-contracts/core-contracts/precompiled.md b/docs/develop/smart-contracts/core-contracts/precompiled.md
new file mode 100644
index 0000000000..d401383282
--- /dev/null
+++ b/docs/develop/smart-contracts/core-contracts/precompiled.md
@@ -0,0 +1,39 @@
+# Precompiled Contracts
+*Precompiled smart contract* is a contract with a C++ implementation in node.
+When a validator runs a transaction on such smart contract, it can execute this implementation instead of TVM.
+This improves performance and allows to reduce computation fees.
+
+## Config
+The list of precompiled contracts is stored in the masterchain config:
+```
+precompiled_smc#b0 gas_usage:uint64 = PrecompiledSmc;
+precompiled_contracts_config#c0 list:(HashmapE 256 PrecompiledSmc) = PrecompiledContractsConfig;
+_ PrecompiledContractsConfig = ConfigParam 45;
+```
+
+`list:(HashmapE 256 PrecompiledSmc)` is a map `(code_hash -> precomplied_smc)`.
+If the code hash of a contract is found in this map then the contract is considered *precompiled*.
+
+## Contract execution
+Any transaction on a *precompiled smart contract* (i.e. any contract with code hash found in `ConfigParam 45`) is executed in as follows:
+1. Get `gas_usage` from the masterchain config.
+2. If the balance is not enough to pay for `gas_usage` gas then the compute phase fails with skip reason `cskip_no_gas`.
+3. Code can be executed in two ways:
+ 1. If the precompiled execution is disabled or the C++ implementation is not available in the current version of the node then TVM runs as usual. Gas limit for TVM is set to the transaction gas limit (1M gas).
+ 2. If the precompiled implementation is enabled and available then the C++ implementation is executed.
+4. Override [compute phase values](https://github.com/ton-blockchain/ton/blob/dd5540d69e25f08a1c63760d3afb033208d9c99b/crypto/block/block.tlb#L308): set `gas_used` to `gas_usage`; set `vm_steps`, `vm_init_state_hash`, `vm_final_state_hash` to zero.
+5. Computation fees are based on `gas_usage`, not the actual TVM gas usage.
+
+When precompiled contract is executed in TVM, the 17th element of `c7` is set to `gas_usage` and can be retrieved by `GETPRECOMPILEDGAS` instruction. For non-precompiled contracts this value is `null`.
+
+The execution of precompiled contracts is disabled by default. Run `validator-engine` with `--enable-precompiled-smc` flag to enable it.
+
+Note that both ways to execute a precompiled contract yield the same transaction.
+Therefore, validators with and without C++ implementation can safely co-exist in the network.
+This allows adding new entries to `ConfigParam 45` without requiring all validators to update node software immediately.
+
+## Available implementations
+Hic sunt dracones.
+
+## See Also
+- [Governance Contracts](/develop/smart-contracts/governance)
diff --git a/docs/develop/smart-contracts/environment/ide-plugins.md b/docs/develop/smart-contracts/environment/ide-plugins.md
index 4ba3c69271..f8f5c324d6 100644
--- a/docs/develop/smart-contracts/environment/ide-plugins.md
+++ b/docs/develop/smart-contracts/environment/ide-plugins.md
@@ -1,27 +1,30 @@
# IDE plugins
-## VS Code plugin
+## IntelliJ IDEs Plugin
-Visual Studio Code is a free and popular IDE for developers.
-
-- [Marketplace link](https://marketplace.visualstudio.com/items?itemName=tonwhales.func-vscode)
-- [GitHub repository](https://github.com/ton-foundation/vscode-func)
-
-## IntelliJ IDEs Plugin
+![](/img/docs/ton-jetbrains-plugin.png)
:::info
-Could be used for any of JetBrains products.
+This plugin can be used with any JetBrains product.
+(IntelliJ IDEA, WebStorm, PyCharm, CLion, etc.)
:::
There are several ways to install a plugin:
-- Find plugin directly in the IDE plugins section with "**TON Development**" keywords
-- [Marketplace link](https://plugins.jetbrains.com/plugin/18541-ton-development)
+- Find plugin directly in the IDE plugins section with "**TON**" keywords
+- [Marketplace link](https://plugins.jetbrains.com/plugin/23382-ton)
- [GitHub repository](https://github.com/ton-blockchain/intellij-ton)
+## VS Code plugin
+
+Visual Studio Code is a free and popular IDE for developers.
+
+- [Marketplace link](https://marketplace.visualstudio.com/items?itemName=tonwhales.func-vscode)
+- [GitHub repository](https://github.com/ton-foundation/vscode-func)
+
## FunC Sublime Text plugin
- [GitHub repository](https://github.com/savva425/func_plugin_sublimetext3)
-## neovim plugin
+## Neovim
-- [GitHub repository](https://github.com/cryshado/neovim-ton-dev)
\ No newline at end of file
+To enable syntax highlighting in Neovim, follow the installation instructions in the [nvim-treesitter quickstart guide](https://github.com/nvim-treesitter/nvim-treesitter#quickstart).
diff --git a/docs/develop/smart-contracts/environment/installation.md b/docs/develop/smart-contracts/environment/installation.md
index bce39d9887..1ba7ba94df 100644
--- a/docs/develop/smart-contracts/environment/installation.md
+++ b/docs/develop/smart-contracts/environment/installation.md
@@ -1,19 +1,29 @@
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
+import Button from '@site/src/components/button'
-# Installation
-## Javascript SDK
+# Precompiled binaries
-You no longer need to manually install binaries.
-
-All binaries for development and testing are provided with the packages:
+:::caution important
+You no longer need to manually install binaries with Blueprint SDK.
+:::
-* [Choose your Javascript SDK](/develop/smart-contracts/sdk/javascript)
+All binaries for development and testing are provided with the Blueprint SDK.
+````mdx-code-block
+
+````
+Migrate to Blueprint SDK
+````mdx-code-block
+
+````
## Precompiled binaries
+If you don't use Blueprint SDK for smart contracts development, you can use precompiled binaries for your operating system and tool of choice.
+
### Prerequisites
For the local development of TON smart contracts _without Javascript_, you need to prepare binaries of `func`, `fift`, and `lite client` on your device.
@@ -34,7 +44,7 @@ Download the binaries from the table below. Make sure to select the correct ver
| Linux arm64 | [download](https://github.com/ton-blockchain/ton/releases/latest/download/ton-linux-arm64.zip) | | | | `sudo apt install libatomic1 libssl-dev` |
### 2. Setup your binaries
-
+````mdx-code-block
export const Highlight = ({children, color}) => (
);
-
+````
diff --git a/docs/develop/smart-contracts/environment/testnet.md b/docs/develop/smart-contracts/environment/testnet.md
index 9832131e6f..9623754d05 100644
--- a/docs/develop/smart-contracts/environment/testnet.md
+++ b/docs/develop/smart-contracts/environment/testnet.md
@@ -1,4 +1,4 @@
-# Testnet
+# Understanding Testnet
Use the TON test network for development and testing purpose.
@@ -19,9 +19,10 @@ For convenience, almost the entire infrastructure of the mainnet (wallets, API,
* Browser extension: use [mainnet browser extension](https://chrome.google.com/webstore/detail/ton-wallet/nphplpgoakhhjchkkhmiggakijnkhfnd) and [do this](https://github.com/toncenter/ton-wallet#switch-between-mainnettestnet-in-extension).
* Testnet TON Center API: https://testnet.toncenter.com
* Testnet HTTP API: https://testnet.tonapi.io/
-* Testnet bridge: https://ton.org/bridge?testnet=true
+* Testnet bridge: https://bridge.ton.org/?testnet=true
+* Testent dTON GraphQL: https://testnet.dton.io/
## Some third parties
* To switch to [Tonkeeper's testnet](https://tonkeeper.com/), tap the version 5 times in the settings.
-* Testnet CryptoBot: https://t.me/CryptoTestnetBot
\ No newline at end of file
+* Testnet CryptoBot: https://t.me/CryptoTestnetBot
diff --git a/docs/develop/smart-contracts/examples.md b/docs/develop/smart-contracts/examples.md
index 90cb6b0c98..54b0ebcf3e 100644
--- a/docs/develop/smart-contracts/examples.md
+++ b/docs/develop/smart-contracts/examples.md
@@ -9,45 +9,50 @@ Make sure you have thoroughly tested contracts before using them in a production
## FunC Smart Contracts
### Production used Contracts
-| Contracts | Description |
-|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| [wallet-contract](https://github.com/ton-blockchain/wallet-contract) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/ton-blockchain/wallet-contract&name=wallet-contract) | Wallet v4 is proposed version of wallet to replace v3 or older wallets |
-| [liquid-staking-contract](https://github.com/ton-blockchain/liquid-staking-contract/) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/ton-blockchain/liquid-staking-contract/&name=liquid-staking-contract) | Liquid Staking (LSt) is a protocol that connects TON holders of all caliber with hardware node operators to participate in TON Blockchain validation through assets pooling.|
-| [modern_jetton](https://github.com/EmelyanenkoK/modern_jetton) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/EmelyanenkoK/modern_jetton&name=modern_jetton) | Implementation of standard jetton with additional withdraw_tons and withdraw_jettons. |
-| [governance-contract](https://github.com/ton-blockchain/governance-contract) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/ton-blockchain/governance-contract&name=governance-contract) | Core TON Blockchain contracts `elector-code.fc` and `config-code.fc`. |
-| [bridge-func](https://github.com/ton-blockchain/bridge-func) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/ton-blockchain/bridge-func&name=bridge-func) | TON-EVM Toncoin Bridge. |
-| [token-bridge-func](https://github.com/ton-blockchain/token-bridge-func) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/ton-blockchain/token-bridge-func&name=token-bridge-func) | TON-EVM token bridge - FunC smart contracts. |
-| [lockup-wallet-contract/universal](https://github.com/ton-blockchain/lockup-wallet-contract/tree/main/universal) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/ton-blockchain/lockup-wallet-contract/tree/main/universal&name=lockup-wallet-contract/universal) | Universal lockup wallet is contract that can store locked and restricted coins. |
-| [lockup-wallet-contract/vesting](https://github.com/ton-blockchain/lockup-wallet-contract/tree/main/vesting) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/ton-blockchain/lockup-wallet-contract/tree/main/vesting&name=lockup-wallet-contract/vesting) | Vesting wallet smart-contract |
-| [multisig-contract](https://github.com/ton-blockchain/multisig-contract) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/ton-blockchain/multisig-contract&name=multisig-contract) | `(n, k)`-multisig wallet is a wallet with `n` private keys holders, which accepts requests to send messages if the request collects at least `k` signatures of the holders. |
-| [token-contract](https://github.com/ton-blockchain/token-contract) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/ton-blockchain/token-contract&name=token-contract) | Fungible, Non-Fungible, Semi-Fungible Tokens Smart Contracts |
-| [dns-contract](https://github.com/ton-blockchain/dns-contract) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/ton-blockchain/dns-contract&name=dns-contract) | Smart contracts of `.ton` zone. |
-| [nominator-pool](https://github.com/ton-blockchain/nominator-pool) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/ton-blockchain/nominator-pool&name=nominator-pool) | Nominator pool smart contract |
-| [storage](https://github.com/ton-blockchain/ton/tree/master/storage/storage-daemon/smartcont) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/ton-blockchain/ton/tree/master/storage/storage-daemon/smartcont&name=storage) | TON Storage provider and fabric contracts |
+| Contracts | Description |
+|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| [wallet-contract](https://github.com/ton-blockchain/wallet-contract) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/ton-blockchain/wallet-contract&name=wallet-contract) | Wallet v4 is proposed version of wallet to replace v3 or older wallets |
+| [liquid-staking-contract](https://github.com/ton-blockchain/liquid-staking-contract/) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/ton-blockchain/liquid-staking-contract/&name=liquid-staking-contract) | Liquid Staking (LSt) is a protocol that connects TON holders of all caliber with hardware node operators to participate in TON Blockchain validation through assets pooling. |
+| [modern_jetton](https://github.com/EmelyanenkoK/modern_jetton) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/EmelyanenkoK/modern_jetton&name=modern_jetton) | Implementation of standard jetton with additional withdraw_tons and withdraw_jettons. |
+| [highloadwallet-v3](https://github.com/ton-blockchain/highload-wallet-contract-v3) | This wallet is made for who need to send transactions at very high rates. For example, crypto exchanges. |
+| [stablecoin-contract](https://github.com/ton-blockchain/stablecoin-contract) | Jetton-with-governance FunC smart contracts. Used for stablecoins such as USDt. |
+| [governance-contract](https://github.com/ton-blockchain/governance-contract) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/ton-blockchain/governance-contract&name=governance-contract) | Core TON Blockchain contracts `elector-code.fc` and `config-code.fc`. |
+| [bridge-func](https://github.com/ton-blockchain/bridge-func) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/ton-blockchain/bridge-func&name=bridge-func) | TON-EVM Toncoin Bridge. |
+| [token-bridge-func](https://github.com/ton-blockchain/token-bridge-func) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/ton-blockchain/token-bridge-func&name=token-bridge-func) | TON-EVM token bridge - FunC smart contracts. |
+| [lockup-wallet-contract/universal](https://github.com/ton-blockchain/lockup-wallet-contract/tree/main/universal) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/ton-blockchain/lockup-wallet-contract/tree/main/universal&name=lockup-wallet-contract/universal) | Universal lockup wallet is contract that can store locked and restricted coins. |
+| [lockup-wallet-contract/vesting](https://github.com/ton-blockchain/lockup-wallet-contract/tree/main/vesting) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/ton-blockchain/lockup-wallet-contract/tree/main/vesting&name=lockup-wallet-contract/vesting) | Vesting wallet smart-contract |
+| [multisig-contract](https://github.com/ton-blockchain/multisig-contract) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/ton-blockchain/multisig-contract&name=multisig-contract) | `(n, k)`-multisig wallet is a wallet with `n` private keys holders, which accepts requests to send messages if the request collects at least `k` signatures of the holders. |
+| [token-contract](https://github.com/ton-blockchain/token-contract) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/ton-blockchain/token-contract&name=token-contract) | Fungible, Non-Fungible, Semi-Fungible Tokens Smart Contracts |
+| [dns-contract](https://github.com/ton-blockchain/dns-contract) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/ton-blockchain/dns-contract&name=dns-contract) | Smart contracts of `.ton` zone. |
+| [nominator-pool](https://github.com/ton-blockchain/nominator-pool) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/ton-blockchain/nominator-pool&name=nominator-pool) | Nominator pool smart contract |
+| [single-nominator-pool](https://github.com/orbs-network/single-nominator) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/ton-blockchain/nominator-pool&name=nominator-pool) | Single Nominator Pool smart contract |
+| [vesting-contract](https://github.com/ton-blockchain/vesting-contract) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/ton-blockchain/nominator-pool&name=nominator-pool) | Nominator pool smart contract |
+| [storage](https://github.com/ton-blockchain/ton/tree/master/storage/storage-daemon/smartcont) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/ton-blockchain/ton/tree/master/storage/storage-daemon/smartcont&name=storage) | TON Storage provider and fabric contracts |
### Ecosystem Contracts
-| Contracts | Description |
-| --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
-| [telemint](https://github.com/TelegramMessenger/telemint) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/TelegramMessenger/telemint&name=telemint) | Telegram Usenames(`nft-item.fc`) and Telegram Numbers(`nft-item-no-dns.fc`) contracts. |
-| [WTON](https://github.com/TonoxDeFi/WTON) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/TonoxDeFi/WTON&name=WTON) | This smart contract provides an implementation of wrapped toncoin, called WTON |
-| [capped-fungible-token](https://github.com/TonoxDeFi/capped-fungible-token) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/TonoxDeFi/capped-fungible-token&name=capped-fungible-token) | Basic implementation of smart contracts for Jetton wallet and Jetton minter |
-| [getgems-io/nft-contracts](https://github.com/getgems-io/nft-contracts/tree/main/packages/contracts/sources) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/getgems-io/nft-contracts/tree/main/packages/contracts/sources&name=getgems-io/nft-contracts) | Getgems NFT Contracts |
-| [lockup-wallet-deployment](https://github.com/ton-defi-org/lockup-wallet-deployment) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/ton-defi-org/lockup-wallet-deployment&name=lockup-wallet-deployment) | Deploy and run lockup Contract end to end |
-| [wton-contract](https://github.com/ton-community/wton-contract) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/ton-community/wton-contract&name=wton-contract) | wTON contracts |
-| [contract-verifier-contracts](https://github.com/ton-community/contract-verifier-contracts) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/ton-community/contract-verifier-contracts&name=contract-verifier-contracts) | Sources registry contracts which stores an on-chain proof per code cell hash. |
-| [vanity-contract](https://github.com/ton-community/vanity-contract) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/ton-community/vanity-contract&name=vanity-contract) | Smart contract that allows to "mine" any suitable address for any contract. |
-| [ton-config-smc](https://github.com/ton-foundation/ton-config-smc) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/ton-foundation/ton-config-smc&name=ton-config-smc) | Simple contract for storing versioned data in TON Blockchain. |
-| [ratelance](https://github.com/ProgramCrafter/ratelance/tree/main/contracts/func) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/ProgramCrafter/ratelance/tree/main/contracts/func&name=ratelance) | Ratelance is freelance platform that seeks to remove barriers between potential employers and workers. |
-| [ton-forwarder.fc](https://github.com/TrueCarry/ton-contract-forwarder/blob/main/func/ton-forwarder.fc) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/TrueCarry/ton-contract-forwarder/blob/main/func/ton-forwarder.fc&name=ton-forwarder.fc) | Contract that accepts exact sum and forwards it to specified address. On wrong amount or subsequent returns money. |
-| [logger.fc](https://github.com/tonwhales/ton-contracts/blob/master/contracts/logger.fc) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/tonwhales/ton-contracts/blob/master/contracts/logger.fc&name=logger.fc) | Contract that saves data in the local storage. |
-| [ton-nominators](https://github.com/tonwhales/ton-nominators) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/tonwhales/ton-nominators&name=ton-nominators) | Ton Whales Nominator pool source code. |
-| [ton-link-contract-v3](https://github.com/ton-link/ton-link-contract-v3) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/ton-link/ton-link-contract-v3&name=ton-link-contract-v3) | Ton-link allows smart contracts to access data outside of the blockchain while maintaining data security. |
-| [delab-team/fungible-token](https://github.com/delab-team/contracts/tree/main/fungible-token) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/delab-team/contracts/tree/main/fungible-token&name=delab-team/fungible-token) | DeLab TON fungible-token implementation |
-| [whitelisted-wallet.fc](https://github.com/tonwhales/ton-contracts/blob/master/contracts/whitelisted-wallet.fc) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/tonwhales/ton-contracts/blob/master/contracts/whitelisted-wallet.fc&name=whitelisted-wallet.fc) | Simple Whitelisted Wallet Contract |
-| [delab-team/jetton-pool](https://github.com/delab-team/contracts/tree/main/jetton-pool) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/delab-team/contracts/tree/main/jetton-pool&name=delab-team/jetton-pool) | The Jetton Pool TON smart contract is designed to create farm pools. |
-| [ston-fi/contracts](https://github.com/ston-fi/dex-core/tree/main/contracts) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/ston-fi/dex-core/tree/main/contracts&name=ston-fi/contracts) | Stonfi DEX core contracts |
-| [onda-ton](https://github.com/0xknstntn/onda-ton) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/0xknstntn/onda-ton&name=onda-ton) | Onda Lending Pool - Core smart contracts of the first lending protocol on TON |
-| [ton-stable-timer](https://github.com/ProgramCrafter/ton-stable-timer) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/ProgramCrafter/ton-stable-timer&name=ton-stable-timer) | TON Stable Timer contract |
+| Contracts | Description |
+|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------|
+| [telemint](https://github.com/TelegramMessenger/telemint) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/TelegramMessenger/telemint&name=telemint) | Telegram Usenames(`nft-item.fc`) and Telegram Numbers(`nft-item-no-dns.fc`) contracts. |
+| [capped-fungible-token](https://github.com/TonoxDeFi/capped-fungible-token) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/TonoxDeFi/capped-fungible-token&name=capped-fungible-token) | Basic implementation of smart contracts for Jetton wallet and Jetton minter |
+| [gusarich-airdrop](https://github.com/Gusarich/airdrop/tree/main/contracts) | Implementation of a Scalable Airdrop System for the TON blockchain. It can be used to distribute Jettons on-chain to any number of wallets. |
+| [getgems-io/nft-contracts](https://github.com/getgems-io/nft-contracts/tree/main/packages/contracts/sources) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/getgems-io/nft-contracts/tree/main/packages/contracts/sources&name=getgems-io/nft-contracts) | Getgems NFT Contracts |
+| [lockup-wallet-deployment](https://github.com/ton-defi-org/lockup-wallet-deployment) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/ton-defi-org/lockup-wallet-deployment&name=lockup-wallet-deployment) | Deploy and run lockup Contract end to end |
+| [WTON](https://github.com/TonoxDeFi/WTON) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/TonoxDeFi/WTON&name=WTON) | This smart contract provides an implementation of wrapped toncoin, called WTON |
+| [wton-contract](https://github.com/ton-community/wton-contract) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/ton-community/wton-contract&name=wton-contract) | wTON contracts |
+| [contract-verifier-contracts](https://github.com/ton-community/contract-verifier-contracts) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/ton-community/contract-verifier-contracts&name=contract-verifier-contracts) | Sources registry contracts which stores an on-chain proof per code cell hash. |
+| [vanity-contract](https://github.com/ton-community/vanity-contract) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/ton-community/vanity-contract&name=vanity-contract) | Smart contract that allows to "mine" any suitable address for any contract. |
+| [ton-config-smc](https://github.com/ton-foundation/ton-config-smc) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/ton-foundation/ton-config-smc&name=ton-config-smc) | Simple contract for storing versioned data in TON Blockchain. |
+| [ratelance](https://github.com/ProgramCrafter/ratelance/tree/main/contracts/func) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/ProgramCrafter/ratelance/tree/main/contracts/func&name=ratelance) | Ratelance is freelance platform that seeks to remove barriers between potential employers and workers. |
+| [logger.fc](https://github.com/tonwhales/ton-contracts/blob/master/contracts/logger.fc) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/tonwhales/ton-contracts/blob/master/contracts/logger.fc&name=logger.fc) | Contract that saves data in the local storage. |
+| [ton-nominators](https://github.com/tonwhales/ton-nominators) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/tonwhales/ton-nominators&name=ton-nominators) | Ton Whales Nominator pool source code. |
+| [ton-link-contract-v3](https://github.com/ton-link/ton-link-contract-v3) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/ton-link/ton-link-contract-v3&name=ton-link-contract-v3) | Ton-link allows smart contracts to access data outside of the blockchain while maintaining data security. |
+| [delab-team/fungible-token](https://github.com/delab-team/contracts/tree/main/fungible-token) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/delab-team/contracts/tree/main/fungible-token&name=delab-team/fungible-token) | DeLab TON fungible-token implementation |
+| [whitelisted-wallet.fc](https://github.com/tonwhales/ton-contracts/blob/master/contracts/whitelisted-wallet.fc) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/tonwhales/ton-contracts/blob/master/contracts/whitelisted-wallet.fc&name=whitelisted-wallet.fc) | Simple Whitelisted Wallet Contract |
+| [delab-team/jetton-pool](https://github.com/delab-team/contracts/tree/main/jetton-pool) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/delab-team/contracts/tree/main/jetton-pool&name=delab-team/jetton-pool) | The Jetton Pool TON smart contract is designed to create farm pools. |
+| [ston-fi/contracts](https://github.com/ston-fi/dex-core/tree/main/contracts) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/ston-fi/dex-core/tree/main/contracts&name=ston-fi/contracts) | Stonfi DEX core contracts |
+| [onda-ton](https://github.com/0xknstntn/onda-ton) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/0xknstntn/onda-ton&name=onda-ton) | Onda Lending Pool - Core smart contracts of the first lending protocol on TON |
+| [ton-stable-timer](https://github.com/ProgramCrafter/ton-stable-timer) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/ProgramCrafter/ton-stable-timer&name=ton-stable-timer) | TON Stable Timer contract |
+| [HipoFinance/contract](https://github.com/HipoFinance/contract) 🪄 [Run in WebIDE](https://ide.nujan.io/?importURL=https://github.com/HipoFinance/contract&name=HipoFinance) | hTON is a decentralized, permission-less, open-source liquid staking protocol on TON Blockchain |
### Learning Contracts
@@ -146,11 +151,11 @@ Make sure you have thoroughly tested contracts before using them in a production
## Add Reference
-If you want share new example smart contract, make your PR for this [page](https://github.com/ton-community/ton-docs/tree/main/docs/develop/smart-contracts/examples.md).
+If you want to share a new example smart contract, make your PR for this [page](https://github.com/ton-community/ton-docs/tree/main/docs/develop/smart-contracts/examples.md).
## See Also
* [Develop Smart Contracts Introduction](/develop/smart-contracts/)
* [How to work with wallet smart contracts](/develop/smart-contracts/tutorials/wallet)
-* [[You Tube] Ton Dev Study FunC & BluePrint lessons](https://www.youtube.com/playlist?list=PLyDBPwv9EPsDjIMAF3XqNI2XGNwdcB3sg)
+* [[You Tube] Ton Dev Study FunC & BluePrint lessons](https://www.youtube.com/watch?v=7omBDfSqGfA&list=PLtUBO1QNEKwtO_zSyLj-axPzc9O9rkmYa)
diff --git a/docs/develop/smart-contracts/fee-calculation.md b/docs/develop/smart-contracts/fee-calculation.md
new file mode 100644
index 0000000000..102e376582
--- /dev/null
+++ b/docs/develop/smart-contracts/fee-calculation.md
@@ -0,0 +1,232 @@
+# Fees Calculation
+
+When your contract starts processing an incoming message, you should check the amount of TONs attached to the message to ensure they are enough to cover [all types of fees](/develop/smart-contracts/fees#elements-of-transaction-fee). To do this, you need to calculate (or predict) the fee for the current transaction.
+
+This document describes how to calculate fees in FunC contracts using the new TVM opcodes.
+
+:::info More information on opcodes
+For a comprehensive list of TVM opcodes, including those mentioned below, check the [TVM instruction page](/learn/tvm-instructions/instructions).
+:::
+
+## Storage Fee
+
+### Overview
+
+In brief, `storage fees` are the amounts you pay for storing a smart contract on the blockchain. You pay for every second the smart contract is stored on the blockchain.
+
+Use the `GETSTORAGEFEE` opcode with the following parameters:
+
+| Param name | Description |
+|:-----------|:--------------------------------------------------------|
+| cells | Number of contract cells |
+| bits | Number of contract bits |
+| is_mc | True if the source or destination is in the masterchain |
+
+:::info Only unique hash cells are counted for storage and fwd fees i.e. 3 identical hash cells are counted as one.
+
+In particular, it deduplicates data: if there are several equivalent sub-cells referenced in different branches, their content is only stored once.
+
+[Read more about deduplication](/develop/data-formats/library-cells).
+:::
+
+### Calculation Flow
+
+Each contract has its balance. You can calculate how many TONs your contract requires to remain valid for a specified `seconds` time using the function:
+
+```func
+int get_storage_fee(int workchain, int seconds, int bits, int cells) asm(cells bits seconds workchain) "GETSTORAGEFEE";
+```
+
+You can then hardcode that value into the contract and calculate the current storage fee using:
+
+```func
+;; functions from func stdlib (not presented on mainnet)
+() raw_reserve(int amount, int mode) impure asm "RAWRESERVE";
+int get_storage_fee(int workchain, int seconds, int bits, int cells) asm(cells bits seconds workchain) "GETSTORAGEFEE";
+int my_storage_due() asm "DUEPAYMENT";
+
+;; constants from stdlib
+;;; Creates an output action which would reserve exactly x nanograms (if y = 0).
+const int RESERVE_REGULAR = 0;
+;;; Creates an output action which would reserve at most x nanograms (if y = 2).
+;;; Bit +2 in y means that the external action does not fail if the specified amount cannot be reserved; instead, all remaining balance is reserved.
+const int RESERVE_AT_MOST = 2;
+;;; in the case of action fail - bounce transaction. No effect if RESERVE_AT_MOST (+2) is used. TVM UPGRADE 2023-07. https://docs.ton.org/learn/tvm-instructions/tvm-upgrade-2023-07#sending-messages
+const int RESERVE_BOUNCE_ON_ACTION_FAIL = 16;
+
+() calculate_and_reserve_at_most_storage_fee(int balance, int msg_value, int workchain, int seconds, int bits, int cells) inline {
+ int on_balance_before_msg = my_ton_balance - msg_value;
+ int min_storage_fee = get_storage_fee(workchain, seconds, bits, cells); ;; can be hardcoded IF CODE OF THE CONTRACT WILL NOT BE UPDATED
+ raw_reserve(max(on_balance_before_msg, min_storage_fee + my_storage_due()), RESERVE_AT_MOST);
+}
+```
+
+If `storage_fee` is hardcoded, **remember to update it** during contract update process. Not all contracts support updating, so this is an optional requirement.
+
+## Computation Fee
+
+### Overview
+
+In most cases use the `GETGASFEE` opcode with the following parameters:
+
+| Param | Description |
+|:-----------|:--------------------------------------------------------|
+| `gas_used` | Gas amount, calculated in tests and hardcoded |
+| `is_mc` | True if the source or destination is in the masterchain |
+
+### Calculation Flow
+
+```func
+int get_compute_fee(int workchain, int gas_used) asm(gas_used workchain) "GETGASFEE";
+```
+
+But how do you get `gas_used`? Through tests!
+
+To calculate `gas_used`, you should write a test for your contract that:
+
+1. Makes a transfer.
+2. Checks if it's successful and retrieves the transfer info.
+3. Checks the actual amount of gas used by that transfer for computation.
+
+Contract computation flow can depend on input data. You should run contract in that way to use as much gas as possible. Make sure that you are using the most expensive compute way to compute contract
+
+```ts
+// Just Init code
+const deployerJettonWallet = await userWallet(deployer.address);
+let initialJettonBalance = await deployerJettonWallet.getJettonBalance();
+const notDeployerJettonWallet = await userWallet(notDeployer.address);
+let initialJettonBalance2 = await notDeployerJettonWallet.getJettonBalance();
+let sentAmount = toNano('0.5');
+let forwardAmount = toNano('0.05');
+let forwardPayload = beginCell().storeUint(0x1234567890abcdefn, 128).endCell();
+// Make sure payload is different, so cell load is charged for each individual payload.
+let customPayload = beginCell().storeUint(0xfedcba0987654321n, 128).endCell();
+
+// Let's use this case for fees calculation
+// Put the forward payload into custom payload, to make sure maximum possible gas is used during computation
+const sendResult = await deployerJettonWallet.sendTransfer(deployer.getSender(), toNano('0.17'), // tons
+ sentAmount, notDeployer.address,
+ deployer.address, customPayload, forwardAmount, forwardPayload);
+expect(sendResult.transactions).toHaveTransaction({ //excesses
+ from: notDeployerJettonWallet.address,
+ to: deployer.address,
+});
+/*
+transfer_notification#7362d09c query_id:uint64 amount:(VarUInteger 16)
+ sender:MsgAddress forward_payload:(Either Cell ^Cell)
+ = InternalMsgBody;
+*/
+expect(sendResult.transactions).toHaveTransaction({ // notification
+ from: notDeployerJettonWallet.address,
+ to: notDeployer.address,
+ value: forwardAmount,
+ body: beginCell().storeUint(Op.transfer_notification, 32).storeUint(0, 64) // default queryId
+ .storeCoins(sentAmount)
+ .storeAddress(deployer.address)
+ .storeUint(1, 1)
+ .storeRef(forwardPayload)
+ .endCell()
+});
+const transferTx = findTransactionRequired(sendResult.transactions, {
+ on: deployerJettonWallet.address,
+ from: deployer.address,
+ op: Op.transfer,
+ success: true
+});
+
+let computedGeneric: (transaction: Transaction) => TransactionComputeVm;
+computedGeneric = (transaction) => {
+ if(transaction.description.type !== "generic")
+ throw("Expected generic transactionaction");
+ if(transaction.description.computePhase.type !== "vm")
+ throw("Compute phase expected")
+ return transaction.description.computePhase;
+}
+
+let printTxGasStats: (name: string, trans: Transaction) => bigint;
+printTxGasStats = (name, transaction) => {
+ const txComputed = computedGeneric(transaction);
+ console.log(`${name} used ${txComputed.gasUsed} gas`);
+ console.log(`${name} gas cost: ${txComputed.gasFees}`);
+ return txComputed.gasFees;
+}
+
+send_gas_fee = printTxGasStats("Jetton transfer", transferTx);
+```
+
+## Forward Fee
+
+### Overview
+
+The forward fee is taken for outgoing messages.
+
+Generally, there are three cases of forward fee processing:
+
+1. The message structure is deterministic and you can predict the fee.
+2. The message structure depends a lot on the incoming message structure.
+3. You can't predict the outgoing message structure at all.
+
+### Calculation Flow
+
+If the message structure is deterministic, use the `GETFORWARDFEE` opcode with the following parameters:
+
+| Param name | Description |
+|:-----------|:---------------------------------------------------------------------------------------|
+| cells | Number of cells |
+| bits | Number of bits |
+| is_mc | True if the source or destination is in the masterchain |
+
+:::info Only unique hash cells are counted for storage and fwd fees i.e. 3 identical hash cells are counted as one.
+
+In particular, it deduplicates data: if there are several equivalent sub-cells referenced in different branches, their content is only stored once.
+
+[Read more about deduplication](/develop/data-formats/library-cells).
+:::
+
+However, sometimes the outgoing message depends significantly on the incoming structure, and in that case, you can't fully predict the fee. Try to use the `GETORIGINALFWDFEE` opcode with the following parameters:
+
+| Param name | Description |
+|:-----------|:----------------------------------------------------|
+| fwd_fee | Parsed from the incoming message |
+| is_mc | True if the source or destination is in the masterchain |
+
+:::caution Be careful with `SENDMSG` opcode
+Next opcode, `SENDMSG`, **is the least optimal way** to calculate fee, but **better than not checking**.
+
+It uses an **unpredictable amount** of gas.
+
+Do not use it unless necessary.
+:::
+
+If even `GETORIGINALFWDFEE` can't be used, there is one more option. Use the `SENDMSG` opcode with the following parameters:
+
+| Param name | Description |
+|:-----------|:-------------|
+| cells | Number of cells |
+| mode | Message mode |
+
+Modes affect the fee calculation as follows:
+- `+1024` do not create action, only estimate fee. Other modes will send a message in action phase.
+- `+128` substitutes the value of the entire balance of the contract before the start of the computation phase (slightly inaccurate, since gas expenses that cannot be estimated before the completion of the computation phase are not taken into account).
+- `+64` substitutes the entire balance of the incoming message as an outcoming value (slightly inaccurate, gas expenses that cannot be estimated before the computation is completed are not taken into account).
+- Other modes can be found [on message modes page](https://docs.ton.org/develop/smart-contracts/messages#message-modes).
+
+It creates an output action and returns a fee for creating a message. However, it uses an unpredictable amount of gas, which can't be calculated using formulas, so how can it be calculated? Use `GASCONSUMED`:
+
+```func
+int send_message(cell msg, int mode) impure asm "SENDMSG";
+int gas_consumed() asm "GASCONSUMED";
+;; ... some code ...
+
+() calculate_forward_fee(cell msg, int mode) inline {
+ int gas_before = gas_consumed();
+ int forward_fee = send_message(msg, mode);
+ int gas_usage = gas_consumed() - gas_before;
+
+ ;; forward fee -- fee value
+ ;; gas_usage -- amount of gas, used to send msg
+}
+```
+
+## See Also
+- [Stablecoin contract with fees calculation](https://github.com/ton-blockchain/stablecoin-contract)
diff --git a/docs/develop/smart-contracts/fees.md b/docs/develop/smart-contracts/fees.md
index 0232239d6b..1a463a5290 100644
--- a/docs/develop/smart-contracts/fees.md
+++ b/docs/develop/smart-contracts/fees.md
@@ -4,12 +4,20 @@ Every TON user should keep in mind that _commission depends on many factors_.
## Gas
-All fees are calculated in Gas. It's a special currency for fees in TON.
+All [computation costs](/develop/howto/fees-low-level#computation-fees) are nominated in gas units and fixed in a certain gas amount.
-All fees are nominated and fixed in a certain gas amount, but the gas price itself is not fixed. Today the price for gas is:
+The price of gas units is determined by the [chain config](https://tonviewer.com/config#20) and may be changed only by consensus of validators. Note that unlike in other systems, the user cannot set his own gas price, and there is no fee market.
+
+Current settings in basechain are as follows: 1 unit of gas costs 400 nanotons.
+
+```cpp
+1 gas = 26214400 / 2^16 nanotons = 0,000 000 4 TON
+```
+
+Current settings in masterchain are as follows: 1 unit of gas costs 10000 nanotons.
```cpp
-1 gas = 1000 nanotons = 0,000 001 TON
+1 gas = 655360000 / 2^16 nanotons = 0,000 01 TON
```
### Average transaction cost
@@ -19,7 +27,7 @@ All fees are nominated and fixed in a certain gas amount, but the gas price itse
Even if TON price increases 100 times, transactions will remain ultra-cheap; less than $0.01. Moreover, validators may lower this value if they see commissions have become expensive [read why they're interested](#gas-changing-voting-process).
:::info
-The current gas amount is written in the Network Config [param 20](https://explorer.toncoin.org/config?workchain=-1&shard=8000000000000000&seqno=22185244&roothash=165D55B3CFFC4043BFC43F81C1A3F2C41B69B33D6615D46FBFD2036256756382&filehash=69C43394D872B02C334B75F59464B2848CD4E23031C03CA7F3B1F98E8A13EE05#configparam20).
+The current gas amount is written in the Network Config [param 20](https://tonviewer.com/config#20) and [param 21](https://tonviewer.com/config#21) for masterchain and basechain respectively.
:::
### Gas changing voting process
@@ -38,15 +46,21 @@ Validators receive a small fee for processing transactions, and charging higher
### How to calculate fees?
-Fees on TON are difficult to calculate in advance, as their amount depends on transaction run time, account status, message content and size, blockchain network settings, and a number of other variables that cannot be calculated until the transaction is sent. Read about [computation fees](/develop/howto/fees-low-level#computation-fees) in low-level article overview.
+Fees on TON are difficult to calculate in advance, as their amount depends on transaction run time, account status, message content and size, blockchain network settings, and a number of other variables that cannot be calculated until the transaction is sent.
That is why even NFT marketplaces usually take an extra amount of TON (_~1 TON_) and return (_`1 - transaction_fee`_) later.
+:::info
+Each contract should check incoming messages for the amount of TONs attached to ensure they are enough to cover the fees.
+
+Check the [low-level fees overview](/develop/howto/fees-low-level) to learn more about the formulas for calculating commissions and [fees calculation](/develop/smart-contracts/fee-calculation) to learn how to calculate fees in FunC contracts using the new TVM opcodes.
+:::
+
However, let's read more about how fees are supposed to function on TON.
## Basic Fees Formula
-According to the [low-level fees overview](/develop/howto/fees-low-level), fees on TON are calculated by this formula:
+Fees on TON are calculated by this formula:
```cpp
transaction_fee = storage_fees
@@ -59,95 +73,13 @@ transaction_fee = storage_fees
## Elements of transaction fee
* `storage_fees` is the amount you pay for storing a smart contract in the blockchain. In fact, you pay for every second the smart contract is stored on the blockchain.
- * _Example_: your TON Wallet is also a smart contract, and it pays a storage fee every time you receive or send a transaction. Read more about [how storage fees are calculated](/develop/smart-contracts/fees#storage-fee).
-* `in_fwd_fees` is a charge for importing messages from outside the blockchain. Every time you make a transaction, it must be delivered to the validators who will process it.
+ * _Example_: your TON Wallet is also a smart contract, and it pays a storage fee every time you receive or send a transaction. Read more about [how storage fees are calculated](/develop/howto/fees-low-level#storage-fee).
+* `in_fwd_fees` is a charge for importing messages only from outside the blockchain, e.g. `external` messages. Every time you make a transaction, it must be delivered to the validators who will process it. For ordinary messages from contract to contract this fee is not applicable. Read [the TON Blockchain paper](https://docs.ton.org/tblkch.pdf) to learn more about inbound messages.
* _Example_: each transaction you make with your wallet app (like Tonkeeper) requires first to be distributed among validation nodes.
* `computation_fees` is the amount you pay for executing code in the virtual machine. The larger the code, the more fees must be paid.
* _Example_: each time you send a transaction with your wallet (which is a smart contract), you execute the code of your wallet contract and pay for it.
-* `action_fees` is a charge for sending outgoing messages made by a smart contract.
+* `action_fees` is a charge for sending outgoing messages made by a smart contract, updating the smart contract code, updating the libraries, etc.
* `out_fwd_fees` stands for a charge for sending messages outside from TON Blockchain to interact with off-chain services (e.g., logs) and external blockchains.
- * Not used because it's not implemented. So today is equal to 0.
-
-## Storage fee
-
-TON validators collect storage fees from smart contracts.
-
-Storage fees are collected from the smart contract balance at the **Storage phase** of any transaction. Read more about phases and how TVM works [here](/learn/tvm-instructions/tvm-overview#transactions-and-phases).
-
-It’s important to keep in mind that on TON you pay for both the execution of a smart contract and for the **used storage**:
-
-```cpp
-bytes * second
-```
-
-It means you have to pay a storage fee for having TON Wallet (even if it's very-very small).
-
-If you have not used your TON Wallet for a significant period of time (1 year), _you will have to pay a significantly larger commission than usual because the wallet pays commission on sending and receiving transactions_.
-
-### Formula
-
-You can approximately calculate storage fees for smart contracts using this formula:
-
-
-```cpp
- storage_fee = (cells_count * cell_price + bits_count * bit_price)
- / 2^16 * time_delta
-```
-
-Let's examine each value more closely:
-
-* `price`—price for storage for `time_delta` seconds
-* `cells_count`—count of cells used by smart contract
-* `bits_count`—count of bits used by smart contract
-* `cell_price`—price of single cell
-* `bit_price`—price of single bit
-
-Both `cell_price` and `bit_price` could be obtained from Network Config [param 18](https://explorer.toncoin.org/config?workchain=-1&shard=8000000000000000&seqno=22185244&roothash=165D55B3CFFC4043BFC43F81C1A3F2C41B69B33D6615D46FBFD2036256756382&filehash=69C43394D872B02C334B75F59464B2848CD4E23031C03CA7F3B1F98E8A13EE05#configparam18).
-
-Current values are:
-
-* Workchain.
- ```cpp
- bit_price_ps:1
- cell_price_ps:500
- ```
-* Masterchain.
- ```cpp
- mc_bit_price_ps:1000
- mc_cell_price_ps:500000
- ```
-
-### Calculator Example
-
-You can use this JS script to calculate storage price for 1 MB in the workchain for 1 year
-
-```js live
-
-// Welcome to LIVE editor!
-// feel free to change any variables
-
-function storageFeeCalculator() {
-
- const size = 1024 * 1024 * 8 // 1MB in bits
- const duration = 60 * 60 * 24 * 365 // 1 Year in secs
-
- const bit_price_ps = 1
- const cell_price_ps = 500
-
- const pricePerSec = size * bit_price_ps +
- + Math.ceil(size / 1023) * cell_price_ps
-
- let fee = (pricePerSec * duration / 2**16 * 10**-9)
- let mb = (size / 1024 / 1024 / 8).toFixed(2)
- let days = Math.floor(duration / (3600 * 24))
-
- let str = `Storage Fee: ${fee} TON (${mb} MB for ${days} days)`
-
- return str
-}
-
-
-```
## FAQ
@@ -169,11 +101,18 @@ Average fee for minting one NFT is 0.08 TON.
Saving 1 MB of data for one year on TON will cost you 6.01 TON. Note that you don't usually need to store big amounts of data on-chain. Consider [TON Storage](/participate/ton-storage/storage-daemon) if you need decentralized storage.
+### Is it possible to send a gasless transaction?
+
+At present, this opportunity is not available. We are actively working on its development. Please stay tuned for updates.
+
### How to calculate fees in FunC?
* [Smart contract function to calculate forward fees in FunC](https://github.com/ton-blockchain/token-contract/blob/main/misc/forward-fee-calc.fc)
## References
-* ["Low-level fees overview"](/develop/howto/fees-low-level#fees-calculation-formulas)—read about the formulas for calculating commissions.
-* *Based on the [@thedailyton article](https://telegra.ph/Commissions-on-TON-07-22) originally written by [menschee](https://github.com/menschee)*
+* Based on the [@thedailyton article](https://telegra.ph/Commissions-on-TON-07-22) originally written by [menschee](https://github.com/menschee)*
+
+## See Also
+
+* ["Low-level fees overview"](/develop/howto/fees-low-level)—read about the formulas for calculating commissions.
diff --git a/docs/develop/smart-contracts/governance.md b/docs/develop/smart-contracts/governance.md
index c0cd92a476..4b7a659953 100644
--- a/docs/develop/smart-contracts/governance.md
+++ b/docs/develop/smart-contracts/governance.md
@@ -1,10 +1,10 @@
-# Governance contracts
+# Governance Contracts
In TON, consensus parameters of node operation related to TVM, catchain, fees, and chain topology (as well as how those parameters are stored and updated) are controlled by a set of special smart contracts (in contrast to the old-fashioned and inflexible ways of hardcoding those parameters adopted by blockchains of previous generations). That way, TON implements comprehensive and transparent on-chain governance. The set of special contracts itself is governed by parameters and currently includes the Elector, Config, and DNS contracts and in future will be extended by extra-currency Minter and others.
## Elector
-The Elector smart contract controls the way how rounds of validation change each other, who gets the duty to validate the blockchain, and how rewards for validation would be distributed. If you want to become a validator and interact with Elector, check [validator instrucitons](https://ton.org/validator).
+The Elector smart contract controls the way how rounds of validation change each other, who gets the duty to validate the blockchain, and how rewards for validation would be distributed. If you want to become a validator and interact with Elector, check [validator instructions](https://ton.org/validator).
Elector stores data of Toncoin that is not withdrawn in `credits` hashmap, new applications in `elect` hashmap, and information about previous elections in _past\_elections_ hashmap (the latter is stored inside _complaints_ about validator misbehavior and _frozen_-stakes of validator for already finished rounds, which are withheld for `stake_held_for`(ConfigParam 15)). The Elector contract has three purposes:
- Process applications for the election of validators
@@ -43,7 +43,8 @@ Each validator, from time to time, is randomly assigned to create a new block (i
### Distribution of validation rewards
The same way as with checking whether it is time to conduct new elections, the Elector in each block checks whether it is time to release funds from `frozen` for stored `past_elections`. At the corresponding block, the Elector distributes accumulated earnings from corresponding validation rounds (gas fees and block creation rewards) to validators of that round proportional to validator weights. After that, stakes with rewards are added to the `credits` table, and the election gets removed from `past_elections` table.
-
+### Current state of Elector
+You can check current state in the [dapp](https://1ixi1.github.io/elector/), which allows to see elections participans, locked stakes, ready to withdraw funds, complaints and so on.
## Config
Config smart contract controls TON configuration parameters. Its logic determines who and under what conditions has permission to change some of those parameters. It also implements a proposal/voting mechanism and validator set rolling updates.
@@ -65,3 +66,9 @@ Validators indeed voted to assign that key to TON Foundation in July 2021 (maste
History of emergency updates:
- On April 17, 2022, the number of applications for the election grew big enough that the election could not be conducted under gas limits at that moment. In particular, elections required more than 10 million of gas, while the block `soft_limit` and `hard_limit` were set to `10m` and `20m` (ConfigParam 22), `special_gas_limit` and `block_gas_limit` were set to `10m` and `10m`, respectively (ConfigParam 20). That way, new validators cannot be set, and due to reaching the block gas limit, transactions that process internal messages on the masterchain could not be included in the block. In turn, that leads to the inability to vote for configuration updates (it was impossible to win the required number of rounds since the current round was unable to finish). An emergency key was used to update ConfigParam 22 `soft_limit` to 22m and `hard_limit` to 25m (in block `19880281`) and ConfigParam 20 `special_gas_limit` to 20m and `block_gas_limit` to 22m (in block `19880300`). As a result, the election was successfully conducted, the next block consumed `10 001 444` gas. The total postponement of elections was about 6 hours, and the functionality of the base chain was unaffected.
- On March 2, 2023, the number of applications for the election grew big enough that even `20m` were not enough to conduct election. However, this time masterchain continue to process external messages due to higher `hard_limit`. An emergency key was used to update ConfigParam 20 `special_gas_limit` to 25m and `block_gas_limit` to 27m (in block `27747086`). As a result, the election was successfully conducted in next block. The total postponement of elections was about 6 hours, besides elections, functionality of the both master chain and base chain was unaffected.
+ - On November 22, 2023, key was used to [renounce itself](https://t.me/tonblockchain/221) (in block `34312810`). As a result, public key was replaced with 32 zero bytes.
+ - Due to switch to OpenSSL implementation of Ed25519 signature verification, check for special case [all bytes of public key are the same](https://github.com/ton-blockchain/ton/blob/7fcf26771748338038aec4e9ec543dc69afeb1fa/crypto/ellcurve/Ed25519.cpp#L57C1-L57C1) was disabled. As a result, check against zero public key stopped work as intended. Using this issue, emergency key was [updated on December 9](https://t.me/tonstatus/80) yet another time (in block `34665437`, [tx](https://tonscan.org/tx/MU%2FNmSFkC0pJiCi730Fmt6PszBooRZkzgiQMv0sExfY=)) to nothing-in-my-sleeve byte-sequence `82b17caadb303d53c3286c06a6e1affc517d1bc1d3ef2e4489d18b873f5d7cd1` that is `sha256("Not a valid curve point")`. Now, the only way to update network configuration parameters is through validator consensus.
+
+
+## See Also
+- [Precompiled Contracts](/develop/smart-contracts/core-contracts/precompiled)
diff --git a/docs/develop/smart-contracts/guidelines.md b/docs/develop/smart-contracts/guidelines.mdx
similarity index 51%
rename from docs/develop/smart-contracts/guidelines.md
rename to docs/develop/smart-contracts/guidelines.mdx
index ceb13ecaa2..fa997cf31c 100644
--- a/docs/develop/smart-contracts/guidelines.md
+++ b/docs/develop/smart-contracts/guidelines.mdx
@@ -1,9 +1,6 @@
-# Overview
+import Button from '@site/src/components/button'
-:::caution advanced level
-This information can be hard to understand for newcomers.
-So feel free to read about it later.
-:::
+# Overview
This page collects some recommendations and best practices that could be followed when developing new smart contracts on TON Blockchain.
@@ -15,3 +12,36 @@ This page collects some recommendations and best practices that could be followe
* [Paying for processing queries and sending responses](/develop/smart-contracts/guidelines/processing)
* [How and why to shard your TON smart contract. Studying the anatomy of TON's Jettons](https://blog.ton.org/how-to-shard-your-ton-smart-contract-and-why-studying-the-anatomy-of-tons-jettons)
* [TON Keeper founders Oleg Andreev and Oleg Illarionov on TON jettons](https://www.youtube.com/watch?v=oEO29KmOpv4)
+
+
+## TON Course: Contract Development
+
+The [TON Blockchain Course](https://stepik.org/course/176754/) is a comprehensive guide to TON Blockchain development.
+
+- Module 2 is dedicated to __TVM, transactions, scalability and business cases__.
+- Module 3 is dedicated to __smart contract development lifecycle__.
+
+````mdx-code-block
+
+````
+Check TON Blockchain Course
+````mdx-code-block
+
+````
+````mdx-code-block
+
+````
+CHN
+````mdx-code-block
+
+````
+````mdx-code-block
+
+````
+RU
+````mdx-code-block
+
+````
diff --git a/docs/develop/smart-contracts/guidelines/accept.md b/docs/develop/smart-contracts/guidelines/accept.md
index fed5a5a808..fd02e2a7ab 100644
--- a/docs/develop/smart-contracts/guidelines/accept.md
+++ b/docs/develop/smart-contracts/guidelines/accept.md
@@ -1,6 +1,6 @@
-# "accept_message" effects
+# Accept Message Effects
-`accept_message` and `set_gas_limit` may cause not that straightforward effects when doing exactly what it's said in the [stdlib reference](/develop/func/stdlib#accept_message).
+`accept_message` and `set_gas_limit` may cause not that straightforward effects when doing exactly what is said in the [stdlib reference](/develop/func/stdlib#accept_message).
## External messages
diff --git a/docs/develop/smart-contracts/guidelines/ecosystem-messages-layout.mdx b/docs/develop/smart-contracts/guidelines/ecosystem-messages-layout.mdx
new file mode 100644
index 0000000000..653be0ab7f
--- /dev/null
+++ b/docs/develop/smart-contracts/guidelines/ecosystem-messages-layout.mdx
@@ -0,0 +1,197 @@
+import ConceptImage from '@site/src/components/conceptImage';
+import ThemedImage from '@theme/ThemedImage';
+
+# Ecosystem Messages Layout
+
+
+## Sending messages
+
+
+
+
+
+
+## Deploying a contract
+
+
+
+
+
+
+## Burn jettons
+
+* [modern_jetton](https://github.com/EmelyanenkoK/modern_jetton/blob/master/contracts/op-codes.func) smart contract
+
+
+
+
+
+
+
+
+## Request jetton wallet address
+
+* [modern_jetton](https://github.com/EmelyanenkoK/modern_jetton/blob/master/contracts/op-codes.func) smart contract
+
+
+
+
+
+
+
+## Transfer jettons
+
+* [modern_jetton](https://github.com/EmelyanenkoK/modern_jetton/blob/master/contracts/op-codes.func) smart contract
+
+
+
+
+
+
+
+## Mint jettons
+
+* [minter-contract](https://github.com/ton-blockchain/minter-contract/blob/main/contracts/imports/op-codes.fc) smart contract
+
+
+
+
+
+
+
+## Prove SBT ownership to contract
+
+* [nft_contracts](https://github.com/getgems-io/nft-contracts/blob/main/packages/contracts/sources/op-codes.fc) smart contract
+
+
+
+
+
+
+
+## Transfer NFT
+
+* [nft_contracts](https://github.com/getgems-io/nft-contracts/blob/main/packages/contracts/sources/op-codes.fc) smart contract
+
+
+
+
+
+
+
+## Mint NFT
+:::info
+Does not specified by NFT standard for /ton-blockchain /token-contract
+:::
+
+
+
+
+
+
+## Batch mint NFT
+:::info
+Does not specified by NFT standard for /ton-blockchain /token-contract
+:::
+
+
+
+
+
+
+## Destroy SBT by User
+
+* [nft_contracts](https://github.com/getgems-io/nft-contracts/blob/main/packages/contracts/sources/op-codes.fc) smart contract
+
+
+
+
+
+
+
+## Destroy SBT by Admin
+
+* [nft_contracts](https://github.com/getgems-io/nft-contracts/blob/main/packages/contracts/sources/op-codes.fc) smart contract
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/develop/smart-contracts/guidelines/external-messages.md b/docs/develop/smart-contracts/guidelines/external-messages.md
index 960db44cc9..5d31d8578d 100644
--- a/docs/develop/smart-contracts/guidelines/external-messages.md
+++ b/docs/develop/smart-contracts/guidelines/external-messages.md
@@ -9,6 +9,7 @@ For instance, a wallet smart contract expects to receive external messages conta
Notice that all external messages `must be protected` against replay attacks. The validators normally remove an external message from the pool of suggested external messages (received from the network); however, in some situations `another validator` could process the same external message twice (thus creating a second transaction for the same external message, leading to the duplication of the original action). Even worse, a `malicious actor could extract` the external message from the block containing the processing transaction and re-send it later. This could force a wallet smart contract to repeat a payment, for example.
:::
+````mdx-code-block
export const Highlight = ({children, color}) => (
);
-
+````
The simplest way to protect smart contracts from replay attacks related to external messages is to store a 32-bit counter `cur-seqno` in the persistent data of the smart contract, and to expect a `req-seqno` value in (the signed part of) any inbound external messages. Then an external message is accepted only if both the signature is valid and `req-seqno` equals `cur-seqno`. After successful processing, the `cur-seqno` value in the persistent data is increased by one, so the same external message will never be accepted again .
diff --git a/docs/develop/smart-contracts/guidelines/get-methods.md b/docs/develop/smart-contracts/guidelines/get-methods.md
index f7df215b25..ec99d771df 100644
--- a/docs/develop/smart-contracts/guidelines/get-methods.md
+++ b/docs/develop/smart-contracts/guidelines/get-methods.md
@@ -222,7 +222,7 @@ We will use Javascript libraries and tools for the examples below:
- [ton](https://github.com/ton-core/ton) library
- [Blueprint](/develop/smart-contracts/sdk/javascript) SDK
-Let's say there is some contract with a following get method:
+Let's say there is some contract with the following get method:
```func
(int) get_total() method_id {
@@ -340,7 +340,7 @@ int get_total() method_id {
.store_uint(0x18, 6)
.store_slice(sender)
.store_coins(0)
- .store_uint(0, 107)
+ .store_uint(0, 107) ;; default message headers (see sending messages page)
.store_uint(3, 32) ;; response operation code
.store_uint(total, 32) ;; the requested number
.end_cell(), 64);
diff --git a/docs/develop/smart-contracts/guidelines/internal-messages.md b/docs/develop/smart-contracts/guidelines/internal-messages.md
index 1a7ce30f15..33546a4663 100644
--- a/docs/develop/smart-contracts/guidelines/internal-messages.md
+++ b/docs/develop/smart-contracts/guidelines/internal-messages.md
@@ -33,7 +33,7 @@ The message body typically begins with the following fields:
If `op` is zero, then the message is a "simple transfer message with comment". The comment is contained in the remainder of the message body (without any `query_id` field, i.e., starting from the fifth byte). If it does not begin with the byte `0xff`, the comment is a text one; it can be displayed "as is" to the end user of a wallet (after filtering out invalid and control characters and checking that it is a valid UTF-8 string).
- When comment is long enough that it doesn't fit in a cell, non-fitting end of the line is put to the first reference of the cell. This process continues recursively to describe comments that doesn't fit in two or more cells:
+ When comment is long enough that it doesn't fit in a cell, non-fitting end of the line is put to the first reference of the cell. This process continues recursively to describe comments that don't fit in two or more cells:
```
root_cell("0x00000000" - 32 bit, "string" up to 123 bytes)
↳1st_ref("string continuation" up to 127 bytes)
diff --git a/docs/develop/smart-contracts/guidelines/message-delivery-guarantees.mdx b/docs/develop/smart-contracts/guidelines/message-delivery-guarantees.mdx
index 97b0b21871..0abbd3023f 100644
--- a/docs/develop/smart-contracts/guidelines/message-delivery-guarantees.mdx
+++ b/docs/develop/smart-contracts/guidelines/message-delivery-guarantees.mdx
@@ -1,26 +1,139 @@
import ConceptImage from '@site/src/components/conceptImage';
+import ThemedImage from '@theme/ThemedImage';
-# Message Delivery Guarantees
+# Messages and Transactions
TON is an asynchronous blockchain with a complex structure very different from other blockchains. Because of this, new developers often have questions about low-level things in TON. In this article, we will have a look at one of these related to message delivery.
## What is a message?
+A message is a packet of data sent between actors (users, applications, smart contracts). It typically contains information instructing the receiver on what action to perform, such as updating storage or sending a new message.
+````mdx-code-block
+
+
+
+
+
+````
+Working with this type of communication is reminiscent of launching a satellite into space. We know the message we've formed, but after its launch, it is necessary to conduct separate observation to find out what results we will obtain.
+
+
+
+## What is a Transaction?
+
+A transaction in TON consists of the following:
+- the incoming message that initially triggers the contract (special ways to trigger exist)
+- contract actions caused by the incoming message, such as an update to the contract's storage (optional)
+- outgoing generated messages that are sent to other actors (optional)
+
+>Technically, a contract can be triggered through special functions such as [Tick-Tock](/develop/data-formats/transaction-layout#tick-tock), but this function more used for internal TON Blockchain core contracts.
+
+>Not every transaction results in outgoing messages or updates to the contract's storage — this depends on the actions defined by the contract's code.
+
+````mdx-code-block
+
+
+
+````
+
If we look at Ethereum or almost any other synchronous blockchain, each transaction can contain several smart contract calls in it. For example, DEXs perform multiple exchanges in one transaction if there is no liquidity for the selected trading pair.
In an asynchronous system you can't get a response from the destination smart contract in the same transaction. A contract call may take a few blocks to be processed, depending on the length of the route between source and destination.
To achieve the infinite sharding paradigm, it is necessary to ensure full parallelization, which means that the execution of each transactions is independent of every other. Therefore, instead of transactions which affect and change the state of many contracts at one time, each transaction in TON is only executed on a single smart contract and smart contracts communicate through messages. That way, smart contracts can only interact with each other by calling their functions with special messages and getting a response to them via other messages later.
-If a transaction in Ethereum is just a set of function calls in different contracts, a transaction in TON is made up of the inbound message which initially triggered it and a set of outbound messages which are sent to other contracts.
+:::info
+More detailed and accurate description on the [Transaction Layout](/develop/data-formats/transaction-layout) page.
+:::
+
+### Transaction outcome
+
+There is a [TVM exit code](/learn/tvm-instructions/tvm-exit-codes) for transaction which had compute phase, if it is not 0 or 1 then there was an error.
+Also TVM [compute phase may be skipped](/learn/tvm-instructions/tvm-overview#compute-phase-skipped) for some reasons like absence of funds or state.
+
+:::info for toncenter api v3
+To determine successful transaction one should use tx.description.action.success && tx.description.compute_ph.success:
+:::
+```json
+"transactions": [
+ {
+ "description": {
+ . . . . . . . .
+ "action": {
+ "valid": true,
+ "success": true,
+ . . . . . . . .
+ },
+. . . . . . . .
+ "destroyed": false,
+ "compute_ph": {
+ "mode": 0,
+ "type": "vm",
+ "success": true,
+```
+
+Transaction may have one of three results:
+
+- Success, exit code 0 or 1
+- Fail, `aborted: true` without execution
+- Fail, [exit code](/learn/tvm-instructions/tvm-exit-codes), `aborted: true`
+
+:::info for toncenter api v3
+`aborted: true` is a toncenter field, transaction has no such field
+:::
## What is a Logical time?
-In such a system with asynchronous and parallel smart contract calls, it can be hard to define the order of actions to process. That's why each message in TON has it's _Logical time_ or _Lamport time_ (later just _lt_). It is used to understand which event caused another and what a validator needs to process first.
-
-It is strictly guaranteed that the transaction resulting from a message will have a _lt_ greater than the _lt_ of the message. Likewise, the _lt_ of a message sent in some transaction is strictly greater than the _lt_ of the transaction that caused it. As well as this, messages that were sent from one account and transactions which happened on one account are strictly ordered as well. Thanks to this, for every account we always know the order of transactions, received messages and sent messages.
-
-Moreover, if account _A_ sent two messages to account _B_, it is guaranteed that the message with a lower _lt_ will be processed earlier. Otherwise, an attempt to synchronize delivery would require the state of all the others to be known before processing one shard, thereby breaking parallelization and destroying efficient sharding.
+In such a system with asynchronous and parallel smart contract calls, it can be hard to define the order of actions to process. That's why each message in TON has its _Logical time_ or _Lamport time_ (later just _lt_). It is used to understand which event caused another and what a validator needs to process first.
+
+It is strictly guaranteed that the transaction resulting from a message will have a _lt_ greater than the _lt_ of the message. Likewise, the _lt_ of a message sent in some transaction is strictly greater than the _lt_ of the transaction that caused it. As well as this, messages that were sent from one account and transactions which happened on one account are strictly ordered as well.
+
+````mdx-code-block
+
+
+
+````
+For the case in the image, it turns out: `in_msg_lt < tx0_lt < out_msg_lt`
+
+Thanks to this, for every account we always know the order of transactions, received messages and sent messages.
+
+Moreover, if account _A_ sent two messages to account _B_, it is guaranteed that the message with a lower _lt_ will be processed earlier:
+
+If `msg1_lt < msg2_lt` => `tx1_lt < tx2_lt`.
+````mdx-code-block
+
+
+
+
+
+````
+
+
+Otherwise, an attempt to synchronize delivery would require the state of all the others to be known before processing one shard, thereby breaking parallelization and destroying efficient sharding.
For each block, we can define the _lt_ span as starting from the first transaction and ending with the _lt_ of the last event in the block (message or transaction). Blocks are ordered the same way as other events in TON and so if one block depends on the other, it has a higher _lt_. The child block in a shard has a higher _lt_ than its parent. A masterchain block's _lt_ is higher that the _lts_ of shard blocks that it lists, since a master block depends on listed shard blocks. Each shard block contains an ordered reference to the latest (at the moment of shard block creation) master block and thus the shard block _lt_ is higher than the referenced master block _lt_.
@@ -28,32 +141,61 @@ For each block, we can define the _lt_ span as starting from the first transacti
Fortunately, TON works in such a way that any internal message will definitely be received by the destination account. A message cannot be lost anywhere between the source and its destination. External messages are a little bit different since their acceptance to the block is at the validator's discretion however, once the message is accepted into the incoming message queue, it will be delivered.
-### Delivery order
+### Delivery Order
It therefore seems like _lt_ solves the issue about message delivery order, because we know that a transaction with a lower _lt_ will be processed first. But this doesn't work in every scenario.
Suppose that there are two contracts - _A_ and _B_. _A_ receives an external message which triggers it to send two internal messages to _B_, let's call these messages _1_ and _2_. In this simple case, we can be 100% sure that _1_ will be processed by _B_ before _2_ because it has a lower _lt_.
-
+````mdx-code-block
-
+````
But this is just a simple case when we only have two contracts. How does our system works in more complex cases?
-### Several smart contracts
+### Several Smart Contracts
Suppose that we have three contracts - _A_, _B_ and _C_. In a transaction, _A_ sends two internal messages _1_ and _2_: one to _B_ and another to _C_. Even though they were created in an exact order (_1_, then _2_), we can't be sure that _1_ will be processed before _2_. This is the case because routes from _A_ to _B_ and from _A_ to _C_ can differ in length and validator sets. If these contracts are in different shard chains, one of the messages may require several blocks to reach the destination contract.
-
-
+For better clearness suppose our contracts send back messages `msg1'` and `msg2'` after `msg1` and `msg2` executed by `B` and `C` contracts. As a result it will apply `tx2'` and `tx1'` on the contract `A`.
+We have two possible traces for these transaction,
+
+1. The first possible order is `tx1'_lt < tx2'_lt`:
+````mdx-code-block
+
+
+
+
+
+````
+2. The second possible order is `tx2'_lt < tx1'_lt`:
+````mdx-code-block
+
+
+
+
+
+````
The same thing happens in the reverse case, when two contracts _B_ and _C_ send a message to one contract _A_. Even if message `B -> A` was sent before `C -> A`, we can't know which one of them will be delivered first. The `B -> A` route may require more shard chain hops.
-
+````mdx-code-block
-
+````
There can be many possible scenarios of smart contract interactions, and in any scenario with more than 2 contracts, the order of messages delivery may be arbitrary. The only guarantee is that messages from any contract _A_ to any contract _B_ will be processed in order of their logical time. Some examples are below.
-
+````mdx-code-block
-
+````
## Conclusion
The TON blockchain's asynchronous structure creates challenges for message delivery guarantees. Logical time helps to establish event and transaction order but doesn't guarantee message delivery order between multiple smart contracts due to varying routes in shard chains. Despite these complexities, TON ensures internal message delivery, maintaining network reliability. Developers must adapt to these nuances to harness TON's full potential in building innovative decentralized applications.
diff --git a/docs/develop/smart-contracts/guidelines/message-modes-cookbook.mdx b/docs/develop/smart-contracts/guidelines/message-modes-cookbook.mdx
new file mode 100644
index 0000000000..0a154d4e3b
--- /dev/null
+++ b/docs/develop/smart-contracts/guidelines/message-modes-cookbook.mdx
@@ -0,0 +1,140 @@
+# Message Modes Cookbook
+
+Understanding the different modes and flags available for sending messages is important to ensure that your smart contracts behave correctly.
+While [Message-modes](/develop/smart-contracts/messages#message-modes) section provided detailed descriptions of these modes and flags, in this section we will illustrate their practical application with concrete examples.
+
+:::info IMPORTANT
+The result of the error cases is described when the error occurred.
+
+__Note__: The transaction fees used in these examples (e.g., 3 Toncoin) are hypothetical and are used for illustrative purposes only. Actual transaction fees will vary depending on network conditions and other factors.
+:::
+
+## 1. Send a regular message
+
+We currently have 100 Toncoin in the balance of our smart contract. After receiving an internal message with 50 Toncoin, we send a regular message with 20 Toncoin, the transaction fee is 3 Toncoin and will be deducted from the message.
+
+![](/img/docs/message-modes-cookbook/send_regular_message.svg)
+
+| Mode and Flags | Code |
+|:-|:-|
+| `mode` = 0, no `flag` | `send_raw_message(msg, 0)` |
+
+## 2. Send a regular message, no bounce the message on error and ignore it
+
+We currently have 100 Toncoin in the balance of our smart contract. After receiving an internal message with 50 Toncoin, we send a regular message with 20 Toncoin, the transaction fee is 3 Toncoin and will be deducted from the message.
+In case of an error during transaction processing, the message will not bounce and will be ignored.
+
+![](/img/docs/message-modes-cookbook/send_regular_message_and_ignore_errors.svg)
+
+| Mode and Flags | Code |
+|:-|:-|
+| `mode` = 0, `flag` = 2 | `send_raw_message(msg, 2)` |
+
+## 3. Send a regular message and bounce the message on error
+
+We currently have 100 Toncoin in the balance of our smart contract. After receiving an internal message with 50 Toncoin, we send a regular message with 20 Toncoin, the transaction fee is 3 Toncoin and will be deducted from the message,
+if an error occurs during action processing - bounce the message in addition to rolling back the transaction.
+
+![](/img/docs/message-modes-cookbook/send_regular_message_and_bounce_if_error.svg)
+
+| Mode and Flags | Code |
+|:-|:-|
+| `mode` = 0, `flag` = 16 | `send_raw_message(msg, 16)` |
+
+## 4. Send a regular message with separate fees
+
+We have 100 Toncoin on our smart contract balance, we receive an internal message with 50 Toncoin and send a regular message with 20 Toncoin, the total fee is 3 Toncoin and we pay the transfer fee separately (from the contract balance).
+
+![](/img/docs/message-modes-cookbook/send_regular_and_pay_fees_separately.svg)
+
+| Mode and Flags | Code |
+|:-|:-|
+| `mode` = 0, `flag` = 1 | `send_raw_message(msg, 1)` |
+
+## 5. Send a regular message with separate fees and bounce the message on error
+
+We have 100 Toncoin on our smart contract balance and we receive an internal message with 50 Toncoin and send a regular message with 20 Toncoin, the total fee is 3 Toncoin and we pay the transfer fee separately (from the contract balance),
+if an error occurs during action processing - bounce the message in addition to rolling back the transaction.
+
+![](/img/docs/message-modes-cookbook/send_regular_message_pay_fee_separately_bounce_if_error.svg)
+
+| Mode and Flags | Code |
+|:-|:-|
+| `mode` = 0, `flag` = 1 + 16 = 17 | `send_raw_message(msg, 17)` |
+
+## 6. Carry remaining value with new message
+
+We currently have 100 Toncoin in the balance of our smart contract. After receiving an internal message with 50 Toncoin we carry all the remaining value of the inbound message in addition to the value initially indicated in the new message,
+the transaction fee is 3 Toncoin and will be deducted from the message.
+
+![](/img/docs/message-modes-cookbook/сarry_all_the_remaining_value.svg)
+
+| Mode and Flags | Code |
+|:-|:-|
+| `mode` = 64, no `flag` | `send_raw_message(msg, 64)` |
+
+## 7. Carry remaining value with new message with separate fees
+
+We currently have 100 Toncoin in the balance of our smart contract. After receiving an internal message with 50 Toncoin we carry all the remaining value of the inbound message in addition to the value initially indicated in the new message,
+the transaction fee is 3 Toncoin and will be paid separately (from the smart contract balance).
+
+![](/img/docs/message-modes-cookbook/сarry_all_the_remaining_value_and_pay_fees_separately.svg)
+
+| Mode and Flags | Code |
+|:-|:-|
+| `mode` = 64, `flag` = 1 | `send_raw_message(msg, 65)` |
+
+## 8. Carry remaining value and bounce the message on error
+
+We currently have 100 Toncoin in the balance of our smart contract. After receiving an internal message with 50 Toncoin we carry all the remaining value of the inbound message in addition to the value initially indicated in the new message,
+the transaction fee is 3 Toncoin and will be deducted from the message, if an error occurs during action processing - bounce the message in addition to rolling back the transaction.
+
+![](/img/docs/message-modes-cookbook/сarry_all_the_remaining_value_and_if_error_bounce.svg)
+
+| Mode and Flags | Code |
+|:-|:-|
+| `mode` = 64, `flag` = 16 | `send_raw_message(msg, 80)` |
+
+## 9. Carry remaining value with new message with separate fees and bounce the message on error
+
+We currently have 100 Toncoin in the balance of our smart contract. After receiving an internal message with 50 Toncoin we send a message, we transfer the entire contract balance in addition to the original amount received, the transaction fee is 3 Toncoin and will be paid separately (from the smart contract balance),
+if an error occurs during action processing - bounce the message in addition to rolling back the transaction.
+
+![](/img/docs/message-modes-cookbook/сarry_all_the_remaining_value_and_pay_fees_separately_and_if_error_bounce.svg)
+
+| Mode and Flags | Code |
+|:-|:-|
+| `mode` = 64, `flag` = 16 + 1 | `send_raw_message(msg, 81)` |
+
+## 10. Send all received tokens together with the contract balance
+
+We currently have 100 Toncoin in the balance of our smart contract. After receiving an internal message with 50 Toncoin we send a message, we transfer the entire contract balance in addition to the original amount received,
+the transaction fee is 3 Toncoin and will be deducted from the message.
+
+![](/img/docs/message-modes-cookbook/send_all_received_tokens_with_balance.svg)
+
+| Mode and Flags | Code |
+|:-|:-|
+| `mode` = 128, no `flag` | `send_raw_message(msg, 128)` |
+
+## 11. Send all received tokens together with the contract balance and bounce the message on error
+
+We currently have 100 Toncoin in the balance of our smart contract. After receiving an internal message with 50 Toncoin we send a message, we transfer the entire contract balance in addition to the original amount received, the transaction fee is 3 Toncoin and will be deducted from the message,
+if there was an error in processing the action - bounce the message in addition to rolling back the transaction.
+
+![](/img/docs/message-modes-cookbook/send_all_received_tokens_with_balance_and_if_error_bounce.svg)
+
+| Mode and Flags | Code |
+|:-|:-|
+| `mode` = 128, `flag` = 16 | `send_raw_message(msg, 144)` |
+
+## 12. Send all received tokens together with the contract balance and destroy smart-contract
+
+We currently have 100 Toncoin in the balance of our smart contract. After receiving an internal message with 50 Toncoin, we send a message to transfer the entire contract balance in addition to the original amount received and destroy the contract,
+the transaction fee is 3 Toncoin and will be deducted from the message.
+
+![](/img/docs/message-modes-cookbook/send_all_received_tokens_with_balance_and_destroy_sc.svg)
+
+| Mode and Flags | Code |
+|:-|:-|
+| `mode` = 128, `flag` = 32 | `send_raw_message(msg, 160)` |
diff --git a/docs/develop/smart-contracts/guidelines/non-bouncable-messages.md b/docs/develop/smart-contracts/guidelines/non-bouncable-messages.md
index 500172cc7f..e43e567c62 100644
--- a/docs/develop/smart-contracts/guidelines/non-bouncable-messages.md
+++ b/docs/develop/smart-contracts/guidelines/non-bouncable-messages.md
@@ -1,5 +1,5 @@
# Non-bounceable messages
-
+````mdx-code-block
export const Highlight = ({children, color}) => (
);
-
+````
Almost all internal messages sent between smart contracts should be bounceable, i.e., should have their "bounce" bit set. Then, if the destination smart contract does not exist, or if it throws an unhandled exception while processing this message, the message will be "bounced" back carrying the remainder of the original value (minus all message transfer and gas fees). The body of the bounced message will contain 32 bit `0xffffffff` followed by 256 bit from original message, but with the "bounce" flag cleared and the "bounced" flag set. Therefore, all smart contracts should check the "bounced" flag of all inbound messages and either silently accept them (by immediately terminating with a zero exit code) or perform some special processing to detect which outbound query has failed. The query contained in the body of a bounced message should never be executed.
:::info
diff --git a/docs/develop/smart-contracts/guidelines/processing.md b/docs/develop/smart-contracts/guidelines/processing.md
index 967b2a691d..7048c5fe53 100644
--- a/docs/develop/smart-contracts/guidelines/processing.md
+++ b/docs/develop/smart-contracts/guidelines/processing.md
@@ -1,4 +1,4 @@
-# Paying for processing queries and sending responses
+# Forward Fees
In general, if a smart contract wants to send a query to another smart contract, it should pay for sending the internal message to the destination smart contract (message forwarding fees), processing this message at the destination (gas fees), and sending back the answer if required (message forwarding fees).
diff --git a/docs/develop/smart-contracts/guidelines/random-number-generation.md b/docs/develop/smart-contracts/guidelines/random-number-generation.md
index 89d955ac8b..e2e77df6fe 100644
--- a/docs/develop/smart-contracts/guidelines/random-number-generation.md
+++ b/docs/develop/smart-contracts/guidelines/random-number-generation.md
@@ -35,33 +35,6 @@ Skipping blocks isn't a complex task. You can do it by simply sending a message
Do not use this example contract in real projects, write your own instead.
:::
-### Masterchain echo-contract
-
-The purpose of this contract is just to forward the message back to the sender. This can be accomplished in a few FunC lines of code:
-
-```func
-() recv_internal (cell in_msg_full, slice in_msg_body) impure {
- var cs = in_msg_full.begin_parse();
- var flags = cs~load_uint(4);
- if (flags & 1) { ;; ignore bounced messages
- return ();
- }
- slice sender = cs~load_msg_addr();
- send_raw_message(
- begin_cell()
- .store_uint(0x18, 6)
- .store_slice(sender)
- .store_coins(0)
- .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1)
- .store_slice(in_msg_body)
- .end_cell(),
- 64 + 2 ;; send the remaining value of an incoming msg & ignore errors
- );
-}
-```
-
-Just deploy this contract in the Masterchain, and let's move to the main contract.
-
### Main contract in any workchain
Let's write a simple lottery contract as an example. A user will send 1 TON to it, and with a 50% chance, will get 2 TON back.
@@ -87,7 +60,7 @@ const echo_address = "Ef8Nb7157K5bVxNKAvIWreRcF0RcUlzcCA7lwmewWVNtqM3s"a;
.store_uint(0x18, 6)
.store_slice(echo_address)
.store_coins(0)
- .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1)
+ .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1) ;; default message headers (see sending messages page)
.store_uint(1, 32) ;; let 1 be echo opcode in our contract
.store_slice(sender) ;; forward user address
.end_cell(),
@@ -111,7 +84,7 @@ const echo_address = "Ef8Nb7157K5bVxNKAvIWreRcF0RcUlzcCA7lwmewWVNtqM3s"a;
.store_uint(0x18, 6)
.store_slice(user)
.store_coins(2000000000) ;; 2 TON
- .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1)
+ .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1) ;; default message headers (see sending messages page)
.end_cell(),
3 ;; ignore errors & pay fees separately
);
diff --git a/docs/develop/smart-contracts/libraries.md b/docs/develop/smart-contracts/libraries.md
index 2e093f165b..5508e4cbc1 100644
--- a/docs/develop/smart-contracts/libraries.md
+++ b/docs/develop/smart-contracts/libraries.md
@@ -3,13 +3,15 @@
## Standard libraries
- [stdlib](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/stdlib.fc) — Standard library for FunC
+ - [mathlib](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/mathlib.fc) — Fixed-point mathematical library
## Libraries from Community
- - [open-contracts/utils](https://github.com/TonoxDeFi/open-contracts/tree/main/contracts/utils) — Utility library
+ - [continuation-team/openlib.func](https://github.com/continuation-team/openlib.func) - Reduces transaction fees in common scenarios.
+ - [open-contracts/utils](https://github.com/TonoxDeFi/open-contracts/tree/main/contracts/utils) — Utility library
- [open-contracts/strings](https://github.com/TonoxDeFi/open-contracts/tree/main/contracts/strings) — Provides operations on strings
- [open-contracts/math](https://github.com/TonoxDeFi/open-contracts/tree/main/contracts/math) — Math library that extends FunC arithmetic operations
- - [open-contracts/tuples](https://github.com/TonoxDeFi/open-contracts/tree/main/contracts/tuples) — Collection of tuple-releated functions for FunC
+ - [open-contracts/tuples](https://github.com/TonoxDeFi/open-contracts/tree/main/contracts/tuples) — Collection of tuple-related functions for FunC
- [open-contracts/crypto](https://github.com/TonoxDeFi/open-contracts/tree/main/contracts/crypto) — Provides operations on curve secp256k1
- [toncli/test-libs](https://github.com/disintar/toncli/tree/master/src/toncli/lib/test-libs) - Operations on TLB, generation and parsing of typical messages and types
- [ston-fi/funcbox](https://github.com/ston-fi/funcbox) - Collection of FunC snippets and utilities.
diff --git a/docs/develop/smart-contracts/messages.md b/docs/develop/smart-contracts/messages.md
index 392b7f3bee..73047ffc22 100644
--- a/docs/develop/smart-contracts/messages.md
+++ b/docs/develop/smart-contracts/messages.md
@@ -1,6 +1,6 @@
# Sending messages
-Composition, parsing, and sending messages lie at the intersection of [TL-B schemas](/learn/overviews/TL-B), [transaction phases and TVM](/learn/tvm-instructions/tvm-overview.md).
+Composition, parsing, and sending messages lie at the intersection of [TL-B schemas](/develop/data-formats/tl-b-language), [transaction phases and TVM](/learn/tvm-instructions/tvm-overview).
Indeed, FunC exposes [send_raw_message](/develop/func/stdlib#send_raw_message) function which expects a serialized message as an argument.
@@ -17,6 +17,8 @@ Since TON is a comprehensive system with wide functionality, messages which need
Therefore, the developer should not be afraid, and if something in this document seems incomprehensible on first reading, it's okay. Just grasp the general idea.
+Sometimes the word **'gram'** may be mentioned in the documentation, mostly in code examples, it's just an outdated name for **toncoin**.
+
Let's dive in!
## Types of messages
@@ -56,7 +58,7 @@ ext_out_msg_info$11 src:MsgAddress dest:MsgAddressExt
```
Let's focus on `int_msg_info` for now.
-It starts with 1bit prefix `0`, then there are three 1-bit flags, namely whether Instant Hypercube Routing disabled (currently always true), whether message should be bounced if there are errors during it's processing, whether message itself is result of bounce. Then source and destination addresss are serialized, followed by the value of the message and four integers related to message forwarding fees and time.
+It starts with 1bit prefix `0`, then there are three 1-bit flags, namely whether Instant Hypercube Routing disabled (currently always true), whether message should be bounced if there are errors during its processing, whether message itself is result of bounce. Then source and destination addresses are serialized, followed by the value of the message and four integers related to message forwarding fees and time.
If a message is sent from the smart contract, some of those fields will be rewritten to the correct values. In particular, validator will rewrite `bounced`, `src`, `ihr_fee`, `fwd_fee`, `created_lt` and `created_at`. That means two things: first, another smart-contract during handling message may trust those fields (sender may not forge source address, `bounced` flag, etc); and second, that during serialization we may put to those fields any valid values (anyway those values will be overwritten).
@@ -125,7 +127,7 @@ currencies$_ grams:Grams other:ExtraCurrencyCollection
This scheme means that in addition to the TON value, message may carry the dictionary of additional _extra-currencies_. However, currently we may neglect it and just assume that the message value is serialized as "number of nanotons as variable integer" and "`0` - empty dictionary bit".
-Indeed, in the elector code above we serialize coins' amounts via `.store_coins(grams)` but then just put a string of zeros with length equal to `1 + 4 + 4 + 64 + 32 + 1 + 1`. What is it?
+Indeed, in the elector code above we serialize coins' amounts via `.store_coins(toncoins)` but then just put a string of zeros with length equal to `1 + 4 + 4 + 64 + 32 + 1 + 1`. What is it?
* First bit stands for empty extra-currencies dictionary.
* Then we have two 4-bit long fields. They encode 0 as `VarUInteger 16`. In fact, since `ihr_fee` and `fwd_fee` will be overwritten, we may as well put there zeroes.
* Then we put zero to `created_lt` and `created_at` fields. Those fields will be overwritten as well; however, in contrast to fees, these fields have a fixed length and are thus encoded as 64- and 32-bit long strings.
@@ -152,9 +154,21 @@ Those things should be handled carefully due to the fact that some fields have v
For instance, `MsgAddress` may be represented by four constructors: `addr_none`, `addr_std`, `addr_extern`, `addr_var` with length from 2 bits ( for `addr_none`) to 586 bits (for `addr_var` in the largest form). The same stands for nanotons' amounts which is serialized as `VarUInteger 16`. That means, 4 bits indicating the byte length of the integer and then indicated earlier bytes for integer itself. That way, 0 nanotons will be serialized as `0b0000` (4 bits which encode a zero-length byte string and then zero bytes), while 100.000.000 TON (or 100000000000000000 nanotons) will be serialized as `0b10000000000101100011010001010111100001011101100010100000000000000000` (`0b1000` stands for 8 bytes and then 8 bytes themselves).
+:::info message size
+Note that message has general size limits and cell count limits too,
+e.g.: maximum message size must not exceed `max_msg_bits`, the number of cells per message must not exceed `max_msg_cells`...
+
+More configuration parameters and there values can be found [here](/develop/howto/blockchain-configs#param-43).
+:::
+
## Message modes
-As you might've noticed, we send messages with `send_raw_message` which, apart from consuming the message itself, also accepts the mode. To figure out the mode that best suits your needs, take a look at the following table:
+As you might've noticed, we send messages with `send_raw_message` which, apart from consuming the message itself, also accepts the mode. This mode is used to determine the mode for sending messages, including whether to pay for fuel separately and how to handle errors. When the TON Virtual Machine (TVM) analyses and processes messages, it performs differentiated processing depending on the mode value. Easily confused is that the value of the mode parameter has two variables, namely mode and flag. Mode and flag have different functions:
+
+- mode : defines the basic behaviour when sending a message, e.g. whether to carry a balance, whether to wait for message processing results, etc. Different mode values represent different sending characteristics, and different values can be combined to meet specific sending requirements.
+- flag : as an addition to the mode, it is used to configure specific message behaviour, such as paying transfer fees separately or ignoring processing errors. The flag is added to the mode to create the final message sending mode.
+
+When using the `send_raw_message` function, it is important to select the appropriate mode and flag combination for your needs. To figure out the mode that best suits your needs, take a look at the following table:
| Mode | Description |
|:-|:-|
@@ -162,10 +176,62 @@ As you might've noticed, we send messages with `send_raw_message` which, apart f
| `64` | Carry all the remaining value of the inbound message in addition to the value initially indicated in the new message |
| `128` | Carry all the remaining balance of the current smart contract instead of the value originally indicated in the message |
-| Flag | Description |
-|:-|:-|
-| `+1` | Pay transfer fees separately from the message value |
-| `+2` | Ignore any errors arising while processing this message during the action phase |
-| `+32` | Current account must be destroyed if its resulting balance is zero (often used with Mode 128) |
+| Flag | Description |
+|:------|:----------------------------------------------------------------------------------------------------|
+| `+1` | Pay transfer fees separately from the message value |
+| `+2` | Ignore some errors arising while processing this message during the action phase (check note below) |
+| `+16` | In the case of action fail - bounce transaction. No effect if `+2` is used. |
+| `+32` | Current account must be destroyed if its resulting balance is zero (often used with Mode 128) |
+
+:::info +2 flag
+Note that `+2` flag ignore only following errors arising while processing message during the action phase:
+1. Not enough Toncoins:
+ - Not enough value to transfer with the message (all of the inbound message value has been consumed).
+ - Not enough funds to process a message.
+ - Not enough value attached to the message to pay forwarding fees.
+ - Not enough extra currency to send with the message.
+ - Not enough funds to pay for an outbound external message.
+2. Message is too large (check [Message size](messages#message-size) for more).
+3. The message has too big Merkle depth.
+
+However, it does not ignore errors in the following scenarios:
+1. The message has an invalid format.
+2. The message mode includes both 64 and 128 mods.
+3. The outbound message has invalid libraries in StateInit.
+4. The external message is not ordinary or includes +16 or +32 flag or both.
+:::
+
+:::info +16 flag
+If contract receives bounceable message, it will process `storage` phase **before** `credit` phase.
+
+Otherwise, it will process `credit` phase **before** `storage` phase.
+
+Check [source code with checks for `bounce-enable` flag](https://github.com/ton-blockchain/ton/blob/master/validator/impl/collator.cpp#L2810).
+:::
+
+:::warning
+1. **+16 flag** - do not use in external messages (e.g. to wallets), because there is no sender to receive the bounced message.
+2. **+2 flag** - important in external messages (e.g. to wallets).
+:::
+
+### Example with use cases
+
+Let's look at an example to make it clearer. Let's imagine a situation where we have 100 Toncoin on our smart contract balance and we receive an internal message with 50 Toncoin and send a message with 20 Toncoin, the total fee is 3 Toncoin.
+
+`IMPORTANT`: The result of the error cases is described when the error occurred.
+
+| Case | Mode and Flags | Code | Result |
+|:-|:-|:-|:-|
+| Send a regular message | `mode` = 0, no `flag` | `send_raw_message(msg, 0)` | `balance` - 100 + 50 - 20 = 130, `send` - 20 - 3 = 17
+| Send a regular message, if there was an error in processing the action, don't rollback the transaction and ignore it | `mode` = 0, `flag` = 2 | `send_raw_message(msg, 2)` | `balance` - 100 + 50, `send` - 0
+| Send a regular message, if there was an error in processing the action - bounce the message in addition to rolling back the transaction | `mode` = 0, `flag` = 16 | `send_raw_message(msg, 16)` | `balance` - 100 + 50 = 167 + 17 (bounced), `send` - 20 - 3 = `bounce` message with 17
+| Send a regular message and pay transfer fees separately | `mode` = 0, `flag` = 1 | `send_raw_message(msg, 1)` | `balance` - 100 + 50 - 20 - 3 = 127, `send` - 20
+| Send a regular message and pay transfer fees separately, if there was an error in processing the action - bounce the message in addition to rolling back the transaction | `mode` = 0, `flags` = 1 + 16 | `send_raw_message(msg, 17)` | `balance` - 100 + 50 - 20 - 3 = 127 + `20 (bounced)`, `send` - 20 = `bounce` message with 20
+| Carry all the remaining value of the inbound message in addition to the value initially indicated in the new message | `mode` = 64, `flag` = 0 | `send_raw_message(msg, 64)` | `balance` - 100 - 20 = 80, `send` - 20 + 50 - 3 = 67
+| Carry all the remaining value of the inbound message in addition to the value initially indicated in the new message and pay transfer fees separately | `mode` = 64, `flag` = 1 | `send_raw_message(msg, 65)` | `balance` - 100 - 20 - 3 = 77, `send` - 20 + 50 = 70
+| Carry all the remaining value of the inbound message in addition to the value initially indicated in the new message and pay transfer fees separately, if there was an error in processing the action - bounce the message in addition to rolling back the transaction | `mode` = 64, `flags` = 1 + 16 | `send_raw_message(msg, 81)` | `balance` - 100 - 20 - 3 = 77 + `70 (bounced)`, `send` - 20 + 50 = `bounce` message with 70
+| Send all received tokens together with the contract balance | `mode` = 128, `flag` = 0 | `send_raw_message(msg, 128)` | `balance` - 0, `send` - 100 + 50 - 3 = 147
+| Send all received tokens together with the contract balance, if there was an error in processing the action - bounce the message in addition to rolling back the transaction | `mode` = 128, `flag` = 16 | `send_raw_message(msg, 144)` | `balance` - 0 + `147 (bounced)`, `send` - 100 + 50 - 3 = `bounce` message with 147
+| Send all received tokens together with the contract balance and destroy smart-contract | `mode` = 128, `flag` = 32 | `send_raw_message(msg, 160)` | `balance` - 0, `send` - 100 + 50 - 3 = 147
+| Send all received tokens together with the contract balance and destroy smart-contract, if there was an error in processing the action - bounce the message in addition to rolling back the transaction. `IMPORTANT: Avoid this behaviour because the refunds will go to an already deleted contract.` | `mode` = 128, `flag` = 32 + 16 | `send_raw_message(msg, 176)` | `balance` - 0 + `147 (bounced)`, `send` - 100 + 50 - 3 = `bounce` message with 147
-To build a mode for the `send_raw_message`, you just have to combine modes and flags by adding them together. For example, if you want to send a regular message and pay transfer fees separately, use the Mode `0` and Flag `+1` to get `mode = 1`. If you want to send the whole contract balance and destroy it immidiately, use the Mode `128` and Flag `+32` to get `mode = 160`.
diff --git a/docs/develop/smart-contracts/sdk/javascript.md b/docs/develop/smart-contracts/sdk/javascript.mdx
similarity index 86%
rename from docs/develop/smart-contracts/sdk/javascript.md
rename to docs/develop/smart-contracts/sdk/javascript.mdx
index 83de912388..e11363c792 100644
--- a/docs/develop/smart-contracts/sdk/javascript.md
+++ b/docs/develop/smart-contracts/sdk/javascript.mdx
@@ -1,6 +1,7 @@
+import Button from '@site/src/components/button'
-# Using Blueprint
+# Blueprint SDK
![Blueprint](\img\blueprint\logo.svg)
@@ -14,6 +15,14 @@ Run the following in terminal to create a new project and follow the on-screen i
npm create ton@latest
```
+````mdx-code-block
+
+````
+Watch Video Tutorials
+````mdx-code-block
+
+````
+
### Core features
- Streamlined workflow for building, testing and deploying smart contracts
diff --git a/docs/develop/smart-contracts/sdk/tonstarter.md b/docs/develop/smart-contracts/sdk/tonstarter.md
index 841d8ce9b5..45a7a95660 100644
--- a/docs/develop/smart-contracts/sdk/tonstarter.md
+++ b/docs/develop/smart-contracts/sdk/tonstarter.md
@@ -4,7 +4,7 @@
Testing toolkit (usually, sandbox) already included to TypeScript SDK named Blueprint.
-- [Read more about Blueprint](develop/smart-contracts/sdk/javascript)
+- [Read more about Blueprint](/develop/smart-contracts/sdk/javascript)
Run tests in one line using:
@@ -18,7 +18,7 @@ npm test
This package allows you to emulate arbitrary TON smart contracts, send messages to them and run get methods on them as if they were deployed on a real network.
-The key difference of this package from ton-contract-executor is the fact that the latter only emulates the compute phase of the contract - it does not know about any other phases and thus does not know anything about fees and balances (in a sense that it does not know whether a contract's balance will be enough to process all the out messages that it produces).
+The key difference between this package and ton-contract-executor is the fact that the latter only emulates the compute phase of the contract - it does not know about any other phases and thus does not know anything about fees and balances (in a sense that it does not know whether a contract's balance will be enough to process all the out messages that it produces).
On the other hand, this package emulates all the phases of a contract, and as a result, the emulation is much closer to what would happen in a real network.
@@ -38,4 +38,4 @@ This library allows you to run TON Virtual Machine locally and execute contract.
Read this article first to understand all approaches to testing on TON:
-* [TON Hello World part 4: Step by step guide for testing your first smart contract](https://ton-community.github.io/tutorials/04-testing/)
\ No newline at end of file
+* [TON Hello World part 4: Step by step guide for testing your first smart contract](https://ton-community.github.io/tutorials/04-testing/)
diff --git a/docs/develop/smart-contracts/security/README.md b/docs/develop/smart-contracts/security/README.md
deleted file mode 100644
index e7f23a8804..0000000000
--- a/docs/develop/smart-contracts/security/README.md
+++ /dev/null
@@ -1,12 +0,0 @@
-# Overview
-
-:::info
-This article needs an update. Please, help us to improve it.
-:::
-
-**This page contains recommendations that can help to secure your smart contract.**
-
-If you are creating a smart contract, then here you can see some examples of what errors can lead you to losing funds:
-
-- [TON Hack Challenge #1](https://github.com/ton-blockchain/hack-challenge-1)
- - [Drawing conclusions from TON Hack Challenge](/develop/smart-contracts/security/ton-hack-challenge-1)
diff --git a/docs/develop/smart-contracts/security/README.mdx b/docs/develop/smart-contracts/security/README.mdx
new file mode 100644
index 0000000000..3a76f49859
--- /dev/null
+++ b/docs/develop/smart-contracts/security/README.mdx
@@ -0,0 +1,50 @@
+import Button from '@site/src/components/button'
+
+# Overview
+
+:::info
+This article needs an update. Please, help us to improve it.
+:::
+
+**This page contains recommendations that can help to secure your smart contract.**
+
+If you are creating a smart contract, then here you can see some examples of what errors can lead you to losing funds:
+
+- [TON Hack Challenge #1](https://github.com/ton-blockchain/hack-challenge-1)
+ - [Drawing conclusions from TON Hack Challenge](/develop/smart-contracts/security/ton-hack-challenge-1)
+
+## TON Course: Security
+
+:::tip
+Before diving into learning about security at the developer level, make sure you have a good understanding of the topic at the user level. To do this, it is recommended that you take a [Blockchain Basics with TON](https://stepik.org/course/201294/promo) ([RU version](https://stepik.org/course/202221/), [CHN version](https://stepik.org/course/200976/)) course, where module 5 covers the basics of security for users.
+:::
+
+The [TON Blockchain Course](https://stepik.org/course/176754/) is a comprehensive guide to TON Blockchain development.
+
+Module 8 completely covers the security of smart contracts on TON Blockchain.
+
+````mdx-code-block
+
+````
+Check TON Blockchain Course
+````mdx-code-block
+
+````
+````mdx-code-block
+
+````
+CHN
+````mdx-code-block
+
+````
+````mdx-code-block
+
+````
+RU
+````mdx-code-block
+
+````
+
diff --git a/docs/develop/smart-contracts/security/secure-programming.mdx b/docs/develop/smart-contracts/security/secure-programming.mdx
new file mode 100644
index 0000000000..7ee393b8a2
--- /dev/null
+++ b/docs/develop/smart-contracts/security/secure-programming.mdx
@@ -0,0 +1,385 @@
+import ThemedImage from '@theme/ThemedImage';
+
+# Secure Smart Contract Programming
+
+In this section, we'll look at a few of the most interesting features of the TON blockchain, and then walk through a list of best practices for developers programming smart contracts on FunC.
+
+## Contract Sharding
+
+When developing contracts for the EVM, you generally break up the project into several contracts for convenience. In some cases, it is possible to implement all the functionality in one contract, and even where contract splitting was necessary (for example, Liquidity Pairs in the Automated Market Maker) this did not lead to any special difficulties. Transactions are executed in their entirety: either everything works out, or everything reverts.
+
+In TON, it is strongly recommended to avoid “unbounded data structures” and [split a single logical contract into small pieces](https://blog.ton.org/how-to-shard-your-ton-smart-contract-and-why-studying-the-anatomy-of-tons-jettons), each of which manages a small amount of data. The basic example is the implementation of TON Jettons. This is TON's version of Ethereum's ERC-20 token standard. Briefly, we have:
+
+
+
+1. One `jetton-minter` that stores `total_supply`, `minter_address`, and a couple of refs: token description (metadata) and `jetton_wallet_code`.
+1. And a lot of jetton-wallet, one for each owner of these jettons. Each such wallet stores only the owner's address, their balance, jetton-minter address, and a link to jetton_wallet_code.
+
+This is necessary so that the transfer of Jettons occurs directly between wallets and does not affect any high-load addresses, which is fundamental for the parallel processing of transactions.
+
+That is, get ready so that your contract turns into a "group of contracts", and they will actively interact with each other.
+
+## Partial Execution of Transactions is Possible
+
+A new unique property appears in the logic of your contract: partial execution of transactions.
+
+For example, consider the message flow of a standard TON Jetton:
+
+![smart1.png](../../../../static/img/docs/security-measures/secure-programming/smart1.png)
+
+As follows from the diagram:
+1. sender sends an `op::transfer` message to its wallet (`sender_wallet`);
+1. `sender_wallet` reduces the token balance;
+1. `sender_wallet` sends an `op::internal_transfer` message to the recipient's wallet (`destination_wallet`);
+1. `destination_wallet` increases its token balance;
+1. `destination_wallet` sends `op::transfer_notification` to its owner (`destination`);
+1. `destination_wallet` returns excess gas with `op::excesses` message on `response_destination` (usually `sender`).
+
+Note that if the `destination_wallet` was unable to process the `op::internal_transfer` message (an exception occurred or the gas ran out), then this part and subsequent steps will not be executed. But the first step (reducing the balance in `sender_wallet`) will be completed. The result is a partial execution of the transaction, an inconsistent state of the `Jetton` and in this case, the loss of money.
+
+In the worst case scenario, all the tokens can be stolen in this way. Imagine that you first accrue bonuses to the user, and then send an `op::burn` message to their Jetton wallet, but you cannot guarantee that the `op::burn` will be processed successfully.
+
+## TON Smart Contract Developer Must Control the Gas
+
+In Solidity, gas is not much of a concern for contract developers. If the user provides too little gas, everything will be reverted as if nothing had happened (but the gas will not be returned). If they provide enough, the actual costs will automatically be calculated and deducted from their balance.
+
+In TON, the situation is different:
+
+1. If there is not enough gas, the transaction will be partially executed;
+1. If there is too much gas, the excess must be returned. This is the developer’s responsibility;
+1. If a “group of contracts” exchanges messages, then control and calculation must be carried out in each message.
+
+TON cannot automatically calculate the gas. The complete execution of the transaction with all its consequences can take a long time, and by the end, the user may not have enough toncoins in their wallet. The carry-value principle is used again here.
+
+## TON Smart Contract Developer Must Manage the Storage
+
+A typical message handler in TON follows this approach:
+
+```func
+() handle_something(...) impure {
+ (int total_supply, ) = load_data();
+ ... ;; do something, change data
+ save_data(total_supply, );
+}
+```
+
+Unfortunately, we are noticing a trend: ` ` is a real enumeration of all contract data fields. For example:
+
+```func
+(
+ int total_supply, int swap_fee, int min_amount, int is_stopped, int user_count, int max_user_count,
+ slice admin_address, slice router_address, slice jettonA_address, slice jettonA_wallet_address,
+ int jettonA_balance, int jettonA_pending_balance, slice jettonB_address, slice jettonB_wallet_address,
+ int jettonB_balance, int jettonB_pending_balance, int mining_amount, int datetime_amount, int minable_time,
+ int half_life, int last_index, int last_mined, cell mining_rate_cell, cell user_info_dict, cell operation_gas,
+ cell content, cell lp_wallet_code
+) = load_data();
+```
+
+This approach has a number of disadvantages.
+
+First, if you decide to add another field, say `is_paused`, then you need to update the `load_data()/save_data()` statements throughout the contract. And this is not only labor-intensive, but it also leads to hard-to-catch errors.
+
+In a recent CertiK audit, we noticed the developer mixed up two arguments in places, and wrote:
+
+```func
+save_data(total_supply, min_amount, swap_fee, ...)
+```
+
+Without an external audit performed by a team of experts, finding such a bug is very difficult. The function was rarely used, and both confused parameters usually had a value of zero. You really have to know what you’re looking for to pick up on an error like this.
+
+Secondly, there is "namespace pollution". Let's explain what the problem is with another example from an audit. In the middle of the function, the input parameter read:
+
+```func
+int min_amount = in_msg_body~load_coins();
+```
+
+That is, there was a shadowing of the storage field by a local variable, and at the end of the function, this replaced value was stored in storage. The attacker had the opportunity to overwrite the state of the contract. The situation is aggravated by the fact that FunC allows the [redeclaration of variables](https://docs.ton.org/develop/func/statements#variable-declaration): “This is not a declaration, but just a compile-time insurance that min_amount has type int.”
+
+And finally, parsing the entire storage and packing it back on every call to every function increases the gas cost.
+
+## Tips
+
+### 1. Always Draw Message Flow Diagrams
+
+Even in a simple contract like a TON Jetton, there are already quite a few messages, senders, receivers, and pieces of data contained in messages. Now imagine how it looks when you’re developing something a little more complex, like a decentralized exchange (DEX) where the number of messages in one workflow can exceed ten.
+
+![smart2.png](../../../../static/img/docs/security-measures/secure-programming/smart2.png)
+
+At CertiK, we use the [DOT](https://en.wikipedia.org/wiki/DOT_(graph_description_language)) language to describe and update such diagrams during the course of the audit. Our auditors find that this helps them visualize and understand the complex interactions within and between contracts.
+
+### 2. Avoid Fails and Catch Bounced Messages
+
+Using the message flow, first define the entry point. This is the message that starts the cascade of messages in your group of contracts (“consequences”). It is here that everything needs to be checked (payload, gas supply, etc.) in order to minimize the possibility of failure in subsequent stages.
+
+If you are not sure whether it will be possible to fulfill all your plans (for example, whether the user has enough tokens to complete the deal), it means that the message flow is probably built incorrectly.
+
+In subsequent messages (consequences), all `throw_if()/throw_unless()` will play the role of asserts rather than actually checking something.
+
+Many contracts also process bounced messages just in case.
+
+For example, in TON Jetton, if the recipient's wallet cannot accept any tokens (it depends on the logic for receiving), then the sender's wallet will process the bounced message and return the tokens to its own balance.
+
+```func
+() on_bounce (slice in_msg_body) impure {
+ in_msg_body~skip_bits(32); ;;0xFFFFFFFF
+
+ (int balance, slice owner_address, slice jetton_master_address, cell jetton_wallet_code) = load_data();
+
+ int op = in_msg_body~load_op();
+
+ throw_unless(error::unknown_op, (op == op::internal_transfer) | (op == op::burn_notification));
+
+ int query_id = in_msg_body~load_query_id();
+ int jetton_amount = in_msg_body~load_coins();
+
+ balance += jetton_amount;
+ save_data(balance, owner_address, jetton_master_address, jetton_wallet_code);
+}
+```
+
+In general, we recommend processing bounced messages, however, they can’t be used as a means of full protection from failed message processing and incomplete execution.
+
+It takes gas to send a bounced message and process it, and if there isn’t enough provided by the sender, then no bounced.
+
+Secondly, TON does not provide for a chain of jumps. This means a bounced message can't be re-bounced. For example, if the second message is sent after the entry message, and the second one triggers the third one, then the entry contract will not be aware of the failure of processing the third message. Similarly, if the processing of the first sends the second and the third, then the failure of the second will not affect the processing of the third.
+
+### 3. Expect a Man-in-the-Middle of the Message Flow
+
+A message cascade can be processed over many blocks. Assume that while one message flow is running, an attacker can initiate a second one in parallel. That is, if a property was checked at the beginning (e.g. whether the user has enough tokens), do not assume that at the third stage in the same contract they will still satisfy this property.
+
+### 4. Use a Carry-Value Pattern
+
+It follows from the previous paragraph that messages between contracts must carry valuables.
+
+In the same TON Jetton, this is demonstrated: `sender_wallet` subtracts the balance and sends it with an `op::internal_transfer` message to `destination_wallet`, and it, in turn, receives the balance with the message and adds it to its own balance (or bounces it back).
+
+And here is an example of incorrect implementation. Why can't you find out your Jetton balance on-chain? Because such a question does not fit the pattern. By the time the response to the `op::get_balance` message reaches the requester, this balance could already have been spent by someone.
+
+In this case, you can implement an alternative:
+![smart3.png](../../../../static/img/docs/security-measures/secure-programming/smart3.png)
+
+1. master sends a message `op::provide_balance` to the wallet;
+1. wallet zeroes its balance and sends back `op::take_balance`;
+1. master receives the money, decides if it has enough, and either uses it (debits something in return) or sends it back to wallet.
+
+### 5. Return Value Instead of Rejecting
+
+From the previous observation, it follows that your group of contracts will often receive not just a request, but a request along with a value. So you can't just refuse to execute the request (via `throw_unless()`), you have to send the Jettons back to the sender.
+
+For example, a typical flow start (see TON Jetton message flow):
+
+1. `sender` sends an `op::transfer` message via `sender_wallet` to `your_contract_wallet`, specifying `forward_ton_amount` and `forward_payload` for your contract;
+1. `sender_wallet` sends an `op::internal_transfer` message to `your_contract_wallet`;
+1. `your_contract_wallet` sends an `op::transfer_notification` message to `your_contract`, delivering `forward_ton_amount`, `forward_payload`, and the `sender_address` and `jetton_amount`;
+1. And here in your contract in `handle_transfer_notification()` the flow begins.
+
+There you need to figure out what kind of request it was, whether there is enough gas to complete it, and whether everything is correct in the payload. At this stage, you should not use `throw_if()/throw_unless()`, because then the Jettons will simply be lost, and the request will not be executed. It's worth using the try-catch statements [available starting from FunC v0.4.0](https://docs.ton.org/develop/func/statements#try-catch-statements).
+
+If something does not meet the expectations of your contract, the Jettons must be returned.
+
+We found an example of this vulnerable implementation in a recent audit.
+
+```func
+() handle_transfer_notification(...) impure {
+...
+ int jetton_amount = in_msg_body~load_coins();
+ slice from_address = in_msg_body~load_msg_addr();
+ slice from_jetton_address = in_msg_body~load_msg_addr();
+
+ if (msg_value < gas_consumption) { ;; not enough gas provided
+ if (equal_slices(from_jetton_address, jettonA_address)) {
+ var msg = begin_cell()
+ .store_uint(0x18, 6)
+ .store_slice(jettonA_wallet_address)
+ .store_coins(0)
+ .store_uint(1, 1 + 4 + 4 + 64 + 32 + 1 + 1)
+ ...
+ }
+ ...
+}
+```
+
+As you can see, here the "return" is sent to `jettonA_wallet_address`, not `sender_address`. Since all decisions are made based on the analysis of `in_msg_body`, an attacker can forge a fake message and extract the money. Always send the return to `sender_address`.
+
+If your contract accepts Jettons, it is impossible to know if it was indeed the expected Jetton that came, or just an `op::transfer_notification` from someone.
+
+If your contract receives unexpected or unknown Jettons, they must also be returned.
+
+### 6. Calculate Gas and Check msg_value
+
+According to our message flow diagram, we can estimate the cost of each handler in each of the scenarios and insert a check for the sufficiency of msg_value.
+
+You can’t just demand with a margin, say 1 TON (the gas_limit on mainnet as of the date of writing) because this gas must be divided among the “consequences”. Let's say your contract sends three messages, then you can only send 0.33 TON to each. This means that they should “demand” less. It’s important to calculate the gas requirements of your whole contract carefully.
+
+Things get more complicated if, during development, your code starts sending more messages. Gas requirements need to be rechecked and updated.
+
+### 7. Return Gas Excesses Carefully
+
+If excess gas is not returned to the sender, the funds will accumulate in your contracts over time. In principle, nothing terrible, this is just suboptimal practice. You can add a function for raking out excesses, but popular contracts like TON Jetton still return to the sender with the message `op::excesses`.
+
+TON has a useful mechanism: `SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE = 64`. When using this mode in `send_raw_message()`, the rest of the gas will be forwarded further with the message (or back) to the new recipient. It is convenient if the message flow is linear: each message handler sends only one message. But there are cases when it is not recommended to use this mechanism:
+
+1. If there are no other non-linear handlers in your contract. storage_fee is deducted from the balance of the contract, and not from the incoming gas. This means that over time, storage_fee can eat up the entire balance because everything that comes in has to go out;
+1. If your contract emits events, i.e. sends a message to an external address. The cost of this action is deducted from the balance of the contract, and not from msg_value.
+```func
+() emit_log_simple (int event_id, int query_id) impure inline {
+ var msg = begin_cell()
+ .store_uint (12, 4) ;; ext_out_msg_info$11 addr$00
+ .store_uint (1, 2) ;; addr_extern$01
+ .store_uint (256, 9) ;; len:(## 9)
+ .store_uint(event_id, 256); ;; external_address:(bits len)
+ .store_uint(0, 64 + 32 + 1 + 1) ;; lt, at, init, body
+ .store_query_id(query_id)
+ .end_cell();
+
+ send_raw_message(msg, SEND_MODE_REGULAR);
+}
+```
+3. If your contract attaches value when sending messages or uses `SEND_MODE_PAY_FEES_SEPARETELY = 1`. These actions deduct from the balance of the contract, which means that returning unused is "working at a loss."
+
+In the indicated cases, a manual approximate calculation of the surplus is used:
+
+```func
+int ton_balance_before_msg = my_ton_balance - msg_value;
+int storage_fee = const::min_tons_for_storage - min(ton_balance_before_msg, const::min_tons_for_storage);
+msg_value -= storage_fee + const::gas_consumption;
+
+if(forward_ton_amount) {
+ msg_value -= (forward_ton_amount + fwd_fee);
+...
+}
+
+if (msg_value > 0) { ;; there is still something to return
+
+var msg = begin_cell()
+ .store_uint(0x10, 6)
+ .store_slice(response_address)
+ .store_coins(msg_value)
+...
+}
+```
+
+Remember, if the value of the contract balance runs out, the transaction will be partially executed, and this cannot be allowed.
+
+### 8. Use Nested Storage
+
+We recommend the following storage organization approach:
+
+```func
+() handle_something(...) impure {
+ (slice swap_data, cell liquidity_data, cell mining_data, cell discovery_data) = load_data();
+ (int total_supply, int swap_fee, int min_amount, int is_stopped) = swap_data.parse_swap_data();
+ …
+ swap_data = pack_swap_data(total_supply + lp_amount, swap_fee, min_amount, is_stopped);
+ save_data(swap_data, liquidity_data, mining_data, discovery_data);
+}
+```
+
+Storage consists of blocks of related data. If a parameter is used in each function, for example, `is_paused`, then it is provided immediately by `load_data()`. If a parameter group is needed only in one scenario, then it does not need to be unpacked, it will not have to be packed, and it will not clog the namespace.
+
+If the storage structure requires changes (usually adding a new field), then much fewer edits will have to be made.
+
+Moreover, the approach can be repeated. If there are 30 storage fields in our contract, then initially you can get four groups, and then get a couple of variables and another subgroup from the first group. The main thing is not to overdo it.
+
+Note that since a cell can store up to 1023 bits of data and up to 4 references, you will have to split the data into different cells anyway.
+
+Hierarchical data is one of the main features of TON, let's use it for its intended purpose.
+
+Global variables can be used, especially at the prototyping stage, where it is not entirely obvious what will be stored in the contract.
+
+```func
+global int var1;
+global cell var2;
+global slice var3;
+
+() load_data() impure {
+ var cs = get_data().begin_parse();
+ var1 = cs~load_coins();
+ var2 = cs~load_ref();
+ var3 = cs~load_bits(512);
+}
+
+() save_data() impure {
+ set_data(
+ begin_cell()
+ .store_coins(var1)
+ .store_ref(var2)
+ .store_bits(var3)
+ .end_cell()
+ );
+}
+```
+
+That way, if you find out that you need another variable, you just add a new global variable and modify `load_data()` and `save_data()`. No changes throughout the contract are needed. However, since there is a limitation on the number of global variables (no more than 31), this pattern can be combined with the "nested storage" recommended above.
+
+Global variables are also often more expensive than storing everything on the stack. This, however, depends on the number of stack permutations, so it is a good idea to prototype with globals and, when storage structure is completely clear, to switch to on stack variables with a "nested" pattern.
+
+### 9. Use end_parse()
+
+Use `end_parse()` wherever possible when reading data from storage and from the message payload. Since TON uses bit streams with variable data format, it’s helpful to ensure that you read as much as you write. This can save you an hour of debugging.
+
+
+### 10. Use More Helper Functions, and Avoid Magic Numbers
+
+This tip is not unique to FunC but it is especially relevant here. Write more wrappers, and helper functions, and declare more constants.
+
+FunC initially has an incredible amount of magic numbers. If the developer does not make any effort to limit their usage, the result is something like this:
+
+```func
+var msg = begin_cell()
+ .store_uint(0xc4ff, 17) ;; 0 11000100 0xff
+ .store_uint(config_addr, 256)
+ .store_grams(1 << 30) ;; ~1 gram of value
+ .store_uint(0, 107)
+ .store_uint(0x4e565354, 32)
+ .store_uint(query_id, 64)
+ .store_ref(vset);
+
+send_raw_message(msg.end_cell(), 1);
+```
+
+This is code from a real project, and it scares off newbies.
+
+Fortunately, in recent versions of FunC, a couple of standard declarations can make the code clearer and more expressive. For example:
+
+```func
+const int SEND_MODE_REGULAR = 0;
+const int SEND_MODE_PAY_FEES_SEPARETELY = 1;
+const int SEND_MODE_IGNORE_ERRORS = 2;
+const int SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE = 64;
+
+builder store_msgbody_prefix_stateinit(builder b) inline {
+ return b.store_uint(4 + 2 + 1, 1 + 4 + 4 + 64 + 32 + 1 + 1 + 1);
+}
+
+builder store_body_header(builder b, int op, int query_id) inline {
+ return b.store_uint(op, 32).store_uint(query_id, 64);
+}
+
+() mint_tokens(slice to_address, cell jetton_wallet_code, int amount, cell master_msg) impure {
+ cell state_init = calculate_jetton_wallet_state_init(to_address, my_address(), jetton_wallet_code);
+ slice to_wallet_address = calculate_address_by_state_init(state_init);
+
+ var msg = begin_cell()
+ .store_msg_flags(BOUNCEABLE)
+ .store_slice(to_wallet_address)
+ .store_coins(amount)
+ .store_msgbody_prefix_stateinit()
+ .store_ref(state_init)
+ .store_ref(master_msg);
+
+ send_raw_message(msg.end_cell(), SEND_MODE_REGULAR);
+}
+```
+
+## References
+
+Originally written by CertiK
+
+- [Original article](https://blog.ton.org/secure-smart-contract-programming-in-func)
+
+
+
+
+
diff --git a/docs/develop/smart-contracts/security/things-to-focus.md b/docs/develop/smart-contracts/security/things-to-focus.md
new file mode 100644
index 0000000000..4f6364ba3e
--- /dev/null
+++ b/docs/develop/smart-contracts/security/things-to-focus.md
@@ -0,0 +1,97 @@
+# Things to Focus on while Working with TON Blockchain
+
+In this article, we will review and discuss the elements to consider for those who want to develop TON applications.
+
+## Checklist
+
+### 1. Name collisions
+
+Func variables and functions may contain almost any legit character. I.e. `var++`, `~bits`, `foo-bar+baz` including commas are valid variables and functions names.
+
+When writing and inspecting a Func code, Linter should be used.
+
+- [IDE plugins](/develop/smart-contracts/environment/ide-plugins/)
+
+### 2. Check the throw values
+
+Each time the TVM execution stops normally, it stops with exit codes `0` or `1`. Although it is done automatically, TVM execution can be interrupted directly in an unexpected way if exit codes `0` and `1` are thrown directly by either `throw(0)` or `throw(1)` command.
+
+- [How to handle errors](/develop/func/builtins#throwing-exceptions)
+- [TVM exit codes](/learn/tvm-instructions/tvm-exit-codes)
+
+### 3. Func is a strictly typed language with data structures holding exactly what they are supposed to store
+
+It is crucial to keep track of what the code does and what it may return. Keep in mind that the compiler cares only about the code and only in its initial state. After certain operations stored values of some variables can change.
+
+Reading unexpected variables values and calling methods on data types that are not supposed to have such methods (or their return values are not stored properly) are errors and are not skipped as "warnings" or "notices" but lead to unreachable code. Keep in mind that storing an unexpected value may be okay, however, reading it may cause problems e.g. error code 5 (integer out of expected range) may be thrown for an integer variable.
+
+### 4. Messages have modes
+
+It is essential to check the message mode, in particular its interaction with previous messages sent and fees. A possible failure is not accounting for storage fees, in which case contract may run out of TON leading to unexpected failures when sending outgoing messages. You can view the message modes [here](/develop/smart-contracts/messages#message-modes).
+
+### 5. TON fully implements the actor model
+
+It means the code of the contract can be changed. It can either be changed permanently, using [`SETCODE`](/develop/func/stdlib#set_code) TVM directive, or in runtime, setting the TVM code registry to a new cell value until the end of execution.
+
+### 6. TON Blockchain has several transaction phases: computational phase, actions phase, and a bounce phase among them
+
+The computational phase executes the code of smart contracts and only then the actions are performed (sending messages, code modification, changing libraries, and others). So, unlike on Ethereum-based blockchains, you won't see the computational phase exit code if you expected the sent message to fail, as it was performed not in the computational phase, but later, during the action phase.
+
+- [Transactions and phases](/learn/tvm-instructions/tvm-overview#transactions-and-phases)
+
+### 7. TON contracts are autonomous
+
+Contracts in the blockchain can reside in separate shards, processed by other set of validators, meaning that developer cannot pull data from other contracts on demand. Thus, any communication is asynchronous and done by sending messages.
+
+- [Sending messages from smart-contract](/develop/smart-contracts/messages)
+- [Sending messages from DApp](/develop/dapps/ton-connect/transactions)
+
+### 8. Unlike other blockchains, TON does not contain revert messages, only exit codes
+
+It is helpful to think through the roadmap of exit codes for the code flow (and have it documented) before starting programming your TON smart contract.
+
+### 9. Func functions that have medhod_id identifiers have method IDs
+
+They can be either set explicitly `"method_id(5)"`, or implicitly by a func compiler. In this case, they can be found among methods declarations in the .fift assembly file. Two of them are predefined: one for receiving messages inside of blockchain `(0)`, commonly named `recv_internal`, and one for receiving messages from outside `(-1)`, `recv_external`.
+
+### 10. TON Crypto address may not have any coins or code
+
+Smart contracts addresses in TON blockchain are deterministic and can be precomputed. Ton Accounts, associated with addresses may even contain no code which means they are uninitialized (if not deployed) or frozen while having no more storage or TON coins if the message with special flags was sent.
+
+### 11. TON addresses may have three representations
+
+TON addresses may have three representations.
+A full representation can either be "raw" (`workchain:address`) or "user-friendly". The last one is the one users encounter most often. It contains a tag byte, indicating whether the address is `bounceable` or `not bounceable`, and a workchain id byte. This information should be noted.
+
+- [Raw and User-Friendly Addresses](https://docs.ton.org/learn/overviews/addresses#raw-and-user-friendly-addresses)
+
+### 12. Keep track of the flaws in code execution
+
+Unlike Solidity where it's up to you to set methods visibility, in the case of Func, the visibility is restricted in a more intricate way either by showing errors or by `if` statements.
+
+### 13. Keep an eye on gas before sending bounced messages
+
+In case the smart contract sends the bounced messages with the value, provided by a user, make sure that the corresponding gas fees are subtracted from the returned amount not to be drained.
+
+### 14. Monitor the callbacks and their failures
+
+TON blockchain is asynchronous. That means the messages do not have to arrive successively. e.g. when a fail notification of an action arrives, it should be handled properly.
+
+### 15. Check if the bounced flag was sent receiving internal messages
+
+You may receive bounced messages (error notifications), which should be handled.
+
+- [Handling of Standard Response Messages](/develop/smart-contracts/guidelines/internal-messages#handling-of-standard-response-messages)
+
+### 16. Write replay protection for external messages:
+
+There are two custom solutions for wallets (smart contracts, storing users money): `seqno-based` (check the counter not to process message twice) and `high-load` (storing processes identifiers and its expirations).
+
+- [Seqno-based wallets](/develop/dapps/asset-processing/#seqno-based-wallets)
+- [High-load wallets](/develop/dapps/asset-processing/#high-load-wallets)
+
+## References
+
+Originally written by 0xguard
+
+- [Original article](https://0xguard.com/things_to_focus_on_while_working_with_ton_blockchain)
\ No newline at end of file
diff --git a/docs/develop/smart-contracts/security/ton-hack-challenge-1.md b/docs/develop/smart-contracts/security/ton-hack-challenge-1.md
index 6d6d7029a1..a4c1714290 100644
--- a/docs/develop/smart-contracts/security/ton-hack-challenge-1.md
+++ b/docs/develop/smart-contracts/security/ton-hack-challenge-1.md
@@ -3,7 +3,7 @@
The TON Hack Challenge was held on October 23.
There were several smart contracts deployed to the TON mainnet with synthetic security breaches. Every contract had a balance of 3000 or 5000 TON, allowing participant to hack it and get rewards immediately.
-Source code and contest rules were hosted on Github [here](https://github.com/ton-blockchain/hack-challenge-1).
+Source code and contest rules were hosted on GitHub [here](https://github.com/ton-blockchain/hack-challenge-1).
## Contracts
@@ -157,5 +157,5 @@ Hope this article has shed some light on the non-obvious rules for FunC develope
Originally written by Dan Volkov
-- [dvlkv on Github](https://github.com/dvlkv)
+- [dvlkv on GitHub](https://github.com/dvlkv)
- [Original article](https://dev.to/dvlkv/drawing-conclusions-from-ton-hack-challenge-1aep)
diff --git a/docs/develop/smart-contracts/testing/overview.mdx b/docs/develop/smart-contracts/testing/overview.mdx
index f879135d4d..ce52bb0b41 100644
--- a/docs/develop/smart-contracts/testing/overview.mdx
+++ b/docs/develop/smart-contracts/testing/overview.mdx
@@ -2,7 +2,7 @@
## Overview
-Test toolkit (usually, sandbox) already included to the TypeScript SDK named [Blueprint](/develop/smart-contracts/sdk/javascript). You can create demo project and launch default test with two steps:
+Test toolkit (usually sandbox) is already included in the TypeScript SDK named [Blueprint](/develop/smart-contracts/sdk/javascript). You can create a demo project and launch the default test with two steps:
1. Create a new Blueprint project:
```bash
@@ -15,7 +15,7 @@ cd MyProject
npx blueprint test
```
-As a result you'll see corresponding output in the terminal window:
+As a result you'll see the corresponding output in the terminal window:
```bash
% npx blueprint test
@@ -36,7 +36,7 @@ Ran all test suites.
## Basic Usage
Testing of smart contracts allows for the coverage of security, optimization of gas spending, and examination of edge cases.
-Writing tests in Blueprint (that based on [Sandbox](https://github.com/ton-org/sandbox)) works through defining arbitary actions with the contract and comparing their results with the expected result, for example:
+Writing tests in Blueprint (based on [Sandbox](https://github.com/ton-org/sandbox)) works through defining arbitrary actions with the contract and comparing test results with the expected result, for example:
```typescript
it('should execute with success', async () => { // description of the test case
@@ -70,15 +70,52 @@ The `toHaveTransaction` matcher expects an object with any combination of fields
| op | number? | Op code is the operation identifier number (crc32 from TL-B usually). Expected in the first 32 bits of a message body. |
|success| boolean? | Custom Sandbox flag that defines the resulting status of a certain transaction. True - if both the compute and the action phase succeeded. Otherwise - False. |
-You can omit those that you're not interested in, and you can also pass in functions accepting those types returning booleans (`true` meaning good) to check for example number ranges, message opcodes, etc. Note however that if a field is optional (like `from?: Address`), then the function needs to accept the optional type, too.
+You can omit the fields that you're not interested in and pass functions accepting the types returning booleans (`true` meaning good) to check for example number ranges, message opcodes, etc. Please note that if a field is optional (like `from?: Address`), then the function needs to accept the optional type, too.
+
:::tip
-Learn the whole list of matcher fields from the [Sandbox documentation](https://github.com/ton-org/sandbox#test-a-transaction-with-matcher).
+You can learn the whole list of matcher fields from the [Sandbox documentation](https://github.com/ton-org/sandbox#test-a-transaction-with-matcher).
:::
+### Specific Test Suite
+
+#### Extract SendMode
+
+To extract the send mode of a sent message you can use the following code:
+
+```ts
+
+const smc = await blockchain.getContract(addr);
+
+const re = blockchain.executor.runTransaction({
+ config: blockchain.configBase64, libs: null, verbosity: 'full',
+ now: Math. floor (Date.now) / 1000),
+ lt: BigInt(Date.now()),
+ randomSeed: null,
+ ignoreChksig: false,
+ debugEnabled: true,
+ shardAccount: beginCell()
+ .store (storeShardAccount (smc.account))
+ .endCell()
+ .toBoc()
+ .toString('base64'),
+ message: beginCell()
+ .store (storeMessageRelaxed (...))
+ .endCell(),
+});
+
+if (!re.result. success || !re.result.actions) {
+ throw new Error('fail');
+}
+const actions = loadoutList(Cell.fromBase64(re.result.actions).beginParse());
+actions[0].type === 'sendMsg' && actions[0].mode;
+
+```
+
+
## Tutorials
-Learn more about testing from most valuable community tutorials on TON:
+Learn more about testing from the most valuable community tutorials on TON:
* [Lesson 2: Testing FunC for a Smart Contract](https://github.com/romanovichim/TonFunClessons_Eng/blob/main/lessons/smartcontract/2lesson/secondlesson.md)
* [TON Hello World part 4: Step by step guide for testing your first smart contract](https://ton-community.github.io/tutorials/04-testing/)
@@ -95,7 +132,7 @@ Check test suites used for TON Ecosystem contracts and learn by examples.
* [governance_tests](https://github.com/Trinketer22/governance_tests/blob/master/elector_tests/tests/complaint-test.fc)
* [MassSender.spec.ts](https://github.com/Gusarich/ton-mass-sender/blob/main/tests/MassSender.spec.ts)
* [TonForwarder.spec.ts](https://github.com/TrueCarry/ton-contract-forwarder/blob/main/src/contracts/ton-forwarder/TonForwarder.spec.ts)
-
+* [Assurer.spec.ts](https://github.com/aSpite/dominant-assurance-contract/blob/main/tests/Assurer.spec.ts)
## See Also
* [Blueprint](/develop/smart-contracts/sdk/javascript)
diff --git a/docs/develop/smart-contracts/testing/tonstarter.md b/docs/develop/smart-contracts/testing/tonstarter.md
index 6749503fda..d2d2f15994 100644
--- a/docs/develop/smart-contracts/testing/tonstarter.md
+++ b/docs/develop/smart-contracts/testing/tonstarter.md
@@ -4,7 +4,7 @@
Testing toolkit (usually, sandbox) already included to TypeScript SDK named Blueprint.
-- [Read more about Blueprint](develop/smart-contracts/sdk/javascript)
+- [Read more about Blueprint](/develop/smart-contracts/sdk/javascript)
Run tests in one line using:
diff --git a/docs/develop/smart-contracts/testing/writing-test-examples.mdx b/docs/develop/smart-contracts/testing/writing-test-examples.mdx
index 4446cfb036..3ed3e3635c 100644
--- a/docs/develop/smart-contracts/testing/writing-test-examples.mdx
+++ b/docs/develop/smart-contracts/testing/writing-test-examples.mdx
@@ -1,8 +1,6 @@
-# Writing Test Examples
+# Writing Tests Examples
-## Writing Tests for Func
-
-This page demonstrates how to write test for FunC contracts created in with [Blueprint](https://github.com/ton-org/blueprint) ([Sandbox](https://github.com/ton-org/sandbox)).
+This page demonstrates how to write test for FunC contracts created in with [Blueprint SDK](https://github.com/ton-org/blueprint) ([Sandbox](https://github.com/ton-org/sandbox)).
Test suites built for demo contract [fireworks](https://github.com/ton-community/fireworks-func). The fireworks is a smart contract which initially run via `set_first` message.
Once a new FunC project is created via `npm create ton@latest`, a test file `tests/contract.spec.ts` will be autogenerated in the project directory for testing the contract:
@@ -33,101 +31,122 @@ Running tests using the following command:
npx blueprint test
```
+Additional options and vmLogs may be specified with `blockchain.verbosity`:
-### Transaction Success Test
+```typescript
+blockchain.verbosity = {
+ ...blockchain.verbosity,
+ blockchainLogs: true,
+ vmLogs: 'vm_logs_full',
+ debugLogs: true,
+ print: false,
+}
+```
-This test checks if the fireworks are successfully set by sending a transaction with a value of 3.5 TON (converted to nanoTON) and the `op::set_first` (`0x5720cfeb`) op code. It then checks if the transaction was successful by validating the `from`, `to`, and `success` fields using the transaction matcher.
+## Direct Unit Tests
-```typescript
+Fireworks demonstrate different operating with sending messages in the TON Blockchain.
- it('should set first fireworks', async () => {
+![](/img/docs/writing-test-examples/test-examples-schemes.svg)
- const launcher = await blockchain.treasury('launcher');
+Once you deploy this with message `set_first` with enough TON amount, it will be automatically executed with primary and usable combinations of send modes.
- const launchResult = await fireworks.sendDeployLaunch(launcher.getSender(), toNano('3.5'));
+Fireworks redeployed itself, as result it will be created 3 entities of Fireworks entities, while each of entity has own ID(keep it in storage) and, as a result, different Smart Contract Address.
+For clearness define different by ID Fireworks instances (different `state_init`) with the following names:
+* 1 - Fireworks setter - The entity that spread different launch op codes. Could be extended up to four different opcodes.
+* 2 - Fireworks launcher-1 - The Fireworks instance, which launch first fireworks, means messages will be sent to the launcher.
+* 3 - Fireworks launcher-2 - The Fireworks instance, which launch second fireworks, means messages will be sent launcher.
- expect(launchResult.transactions).toHaveTransaction({
- from: launcher.address,
- to: fireworks.address,
- op: 0x5720cfeb //set_first
- })
- });
+
+ Expand details on transactions
-```
-This test checks if the fireworks are successfully launched by sending a transaction with a value of 3.5 TON (converted to nanoTON) and the `op::launch_first` (`0x6efe144b`) op code. It then checks if the transaction was successful by validating the `from`, `to`, and `success` fields using the transaction matcher.
+index - is an ID of a transaction in the `launchResult` array.
+* `0` - External request to the treasury (the Launcher) that resulted with a outbound message `op::set_first` with 2.5 to fireworks
+* `1` - The transaction in Fireworks setter contract invoked with `op::set_first` and executed with two outbound messages to the Fireworks Launcher-1 and Fireworks Launcher-2
+* `2` - The transaction in the Fireworks launcher 1 invoked with `op::launch_first`, and executed with four outbound messages to the Launcher.
+* `3` - The transaction in the Fireworks launcher 2 invoked with `op::launch_second`, and executed with a outbound message to the Launcher.
+* `4` - Transaction in the Launcher with incoming message from the Fireworks launcher 1. This message sent with `send mode = 0`.
+* `5` - Transaction in the Launcher with incoming message from the Fireworks launcher 1. This message sent with `send mode = 1`
+* `6` - Transaction in the Launcher with incoming message from the Fireworks launcher 1. This message sent with `send mode = 2`
+* `7` - Transaction in the Launcher with incoming message from the Fireworks launcher 1. This message sent with `send mode = 128 + 32`
+* `8` - Transaction in the Launcher with incoming message from the Fireworks launcher 2. This message sent with `send mode = 64`
-```typescript
- it('should launch first fireworks', async () => {
+
- const launcher = await blockchain.treasury('launcher');
+Each 'firework' - is outbound message with a unique message body appears in transactions with ID:3 and ID:4.
- const launchResult = await fireworks.sendDeployLaunch(launcher.getSender(), toNano('3.5'));
- expect(launchResult.transactions).toHaveTransaction({
- from: fireworks.address,
- op: 0x6efe144b //launch_first
- })
+Bellow the list of test for each transaction expected successfully executed. Transaction[ID:0] External request to the treasury (the Launcher) that resulted with a outbound message `op::set_first` with 2.5 to fireworks. In case you will deploy Fireworks to the blockchain launcher is your wallet.
- printTransactionFees(launchResult.transactions);
- });
+### Transaction ID:1 Success Test
-```
+[This test](https://github.com/ton-community/fireworks-func/blob/main/tests/Fireworks.spec.ts#L75) checks if the fireworks are successfully set by sending a transaction with a value of 2.5 TON.
+This is the simplest case, the main purpose here to assert result of transaction success property to true.
+To filter certain transaction from the `launhcResult.transactions` array, we can use the most convince fields.
+With
+`from` (contract sender address), `to` (contract destination address), `op` (Op code value) - we will retrieve only one transaction for this combination.
-### Account Status Tests
+![](/img/docs/writing-test-examples/test-examples-schemes_id1.svg)
-This test checks if the contract is destroyed after launching the fireworks.
+The transaction[ID:1] in Fireworks Setter contract invoked with `op::set_first` and executed with two outbound messages to the Fireworks launcher-1 and Fireworks launcher-2
```typescript
- it('should destroy after launching', async () => {
+ it('first transaction[ID:1] should set fireworks successfully', async () => {
const launcher = await blockchain.treasury('launcher');
- const launchResult = await fireworks.sendDeployLaunch(
- launcher.getSender(),
- toNano('3.5'),
- );
+ const launchResult = await fireworks.sendDeployLaunch(launcher.getSender(), toNano('2.5'));
- const init_code = code;
- const init_data = beginCell().storeUint(1, 32).endCell();
+ expect(launchResult.transactions).toHaveTransaction({
+ from: launcher.address,
+ to: fireworks.address,
+ success: true,
+ op: Opcodes.set_first
+ })
- const state_init = beginCell()
- .storeUint(0, 1) //no split_depth
- .storeUint(0, 1) // no special
- .storeUint(1, 1) // we have code
- .storeRef(init_code)
- .storeUint(1, 1) // we have data
- .storeRef(init_data)
- .storeUint(0, 1) // we have no library
- .endCell();
+ });
- const hash_dst = state_init.hash
- if (hash_dst === null) {
- throw Error("wrong type");
- }
+```
+### Transaction ID:2 Success Test
- let launched_f1_address = new Address(0, hash_dst());
+[This test](https://github.com/ton-community/fireworks-func/blob/main/tests/Fireworks.spec.ts#L92) checks if the transaction[ID:2] executed successfully.
+![](/img/docs/writing-test-examples/test-examples-schemes_id2.svg)
+
+The transaction in the Fireworks launcher 1 invoked with `op::launch_first`, and executed with four outbound messages to the Launcher.
+
+```typescript
+ it('should exist a transaction[ID:2] which launch first fireworks successfully', async () => {
+
+ const launcher = await blockchain.treasury('launcher');
+
+ const launchResult = await fireworks.sendDeployLaunch(launcher.getSender(), toNano('2.5'));
expect(launchResult.transactions).toHaveTransaction({
from: fireworks.address,
- to: launched_f1_address,
+ to: launched_f1.address,
success: true,
- endStatus: 'non-existing',
- destroyed: true
- });
+ op: Opcodes.launch_first,
+ outMessagesCount: 4,
+ destroyed: true,
+ endStatus: "non-existing",
+ })
- });
+ printTransactionFees(launchResult.transactions);
+ });
```
+In cases, when transaction should affect the state of contract, it is possible to specify this with `destroyed`, `endStatus` fields.
+
The full list of Account Status related fields:
* `destroyed` - `true` - if the existing contract was destroyed due to executing a certain transaction. Otherwise - `false`.
@@ -136,345 +155,179 @@ The full list of Account Status related fields:
* `endStatus` - AccountStatus after transaction execution. Values: `'uninitialized'`, `'frozen'`, `'active'`, `'non-existing'`.
-### Operation Code Tests
-This test shows how to check whether the operation code (op code) of incoming message is equal to the expected op code.
+### Transaction ID:3 Success Test
-```typescript
- it('should be correct op code for the launching first fireworks', async () => {
+[This test](https://github.com/ton-community/fireworks-func/blob/main/tests/Fireworks.spec.ts#L113) checks if the transaction[ID:3] executed successfully.
- const launcher = await blockchain.treasury('launcher');
+![](/img/docs/writing-test-examples/test-examples-schemes_id3.svg)
- const launchResult = await fireworks.sendDeployLaunch(
- launcher.getSender(),
- toNano('3.5'),
- );
-
- const init_code = code;
- const init_data = beginCell().storeUint(1, 32).endCell();
+The transaction[ID:3] carries out in the Fireworks launcher 1, invokes with `op::launch_first`, and executes with four outbound messages to the Launcher.
- const state_init = beginCell()
- .storeUint(0, 1) //no split_depth
- .storeUint(0, 1) // no special
- .storeUint(1, 1) // we have code
- .storeRef(init_code)
- .storeUint(1, 1) // we have data
- .storeRef(init_data)
- .storeUint(0, 1) // we have no library
- .endCell();
-
- const hash_dst = state_init.hash
- if (hash_dst === null) {
- throw Error("wrong type");
- }
+```typescript
+ it('should exist a transaction[ID:3] which launch second fireworks successfully', async () => {
- let launched_f1_address = new Address(0, hash_dst());
+ const launcher = await blockchain.treasury('launcher');
+ const launchResult = await fireworks.sendDeployLaunch(launcher.getSender(), toNano('2.5'));
expect(launchResult.transactions).toHaveTransaction({
from: fireworks.address,
- to: launched_f1_address,
+ to: launched_f2.address,
success: true,
- op: 0x6efe144b, // 'launch_first' expected op code
- outMessagesCount: 4
- });
+ op: Opcodes.launch_second,
+ outMessagesCount: 1
+ })
- expect(launchResult.transactions).toHaveTransaction({
- from: launched_f1_address,
- to: launcher.address,
- success: true,
- op: 0 // 0x00000000 - comment op code
- });
+ printTransactionFees(launchResult.transactions);
});
-```
-> For Tact contracts, crc32 representation could be found in the project build directory, autogenerated with build contract.md file.
-> Read more about [crc32](https://docs.ton.org/develop/data-formats/crc32) and op codes in the TON documentation.
-### Message Counter Tests
-This test checks if the correct number of messages are sent in the transaction.
-For the first fireworks contract:
-```typescript
- it('should be correct op code for the launching first fireworks', async () => {
-
- const launcher = await blockchain.treasury('launcher');
-
- const launchResult = await fireworks.sendDeployLaunch(
- launcher.getSender(),
- toNano('3.5'),
- );
-
- const init_code = code;
- const init_data = beginCell().storeUint(1, 32).endCell();
+```
- const state_init = beginCell()
- .storeUint(0, 1) //no split_depth
- .storeUint(0, 1) // no special
- .storeUint(1, 1) // we have code
- .storeRef(init_code)
- .storeUint(1, 1) // we have data
- .storeRef(init_data)
- .storeUint(0, 1) // we have no library
- .endCell();
- const hash_dst = state_init.hash
- if (hash_dst === null) {
- throw Error("wrong type");
- }
+### Transaction ID:4 Success Test
- let launched_f1_address = new Address(0, hash_dst());
+[This test](https://github.com/ton-community/fireworks-func/blob/main/tests/Fireworks.spec.ts#L133) checks if the transaction[ID:4] executed successfully.
+![](/img/docs/writing-test-examples/test-examples-schemes_id4.svg)
- expect(launchResult.transactions).toHaveTransaction({
- from: fireworks.address,
- to: launched_f1_address,
- success: true,
- op: 0x6efe144b, // 'launch_first' op code
- outMessagesCount: 4
- });
+Transaction[ID:4] carries out in the Launcher(Deploy Wallet) with incoming message from the Fireworks launcher 1. This message sent with `send mode = 0` in the Transaction[ID:2].
- expect(launchResult.transactions).toHaveTransaction({
- from: launched_f1_address,
- to: launcher.address,
- success: true,
- op: 0 // 0x00000000 - comment op code
- });
-
- }); it('fireworks contract should send msgs with comments in first fireworks', async() => {
+```typescript
+ it('should exist a transaction[ID:4] with a comment send mode = 0', async() => {
const launcher = await blockchain.treasury('launcher');
const launchResult = await fireworks.sendDeployLaunch(
launcher.getSender(),
- toNano('3.5'),
+ toNano('2.5'),
);
- const init_code = code;
- const init_data = beginCell().storeUint(1, 32).endCell();
-
-
- const state_init = beginCell()
- .storeUint(0, 1) //no split_depth
- .storeUint(0, 1) // no special
- .storeUint(1, 1) // we have code
- .storeRef(init_code)
- .storeUint(1, 1) // we have data
- .storeRef(init_data)
- .storeUint(0, 1) // we have no library
- .endCell();
-
- const hash_dst = state_init.hash
- if (hash_dst === null) {
- throw Error("wrong type");
- }
-
-
- let launched_f1_address = new Address(0, hash_dst());
-
-
-
expect(launchResult.transactions).toHaveTransaction({
- from: launched_f1_address,
+ from: launched_f1.address,
to: launcher.address,
success: true,
body: beginCell().storeUint(0,32).storeStringTail("send mode = 0").endCell() // 0x00000000 comment opcode and encoded comment
});
+ })
+```
- expect(launchResult.transactions).toHaveTransaction({
- from: launched_f1_address,
- to: launcher.address,
- success: true,
- body: beginCell().storeUint(0,32).storeStringTail("send mode = 1").endCell()
- });
- expect(launchResult.transactions).toHaveTransaction({
- from: launched_f1_address,
- to: launcher.address,
- success: true,
- body: beginCell().storeUint(0,32).storeStringTail("send mode = 2").endCell()
- });
+### Transaction ID:5 Success Test
- expect(launchResult.transactions).toHaveTransaction({
- from: launched_f1_address,
- to: launcher.address,
- success: true,
- body: beginCell().storeUint(0,32).storeStringTail("send mode = 32 + 128").endCell()
- });
- })
+[This test](https://github.com/ton-community/fireworks-func/blob/main/tests/Fireworks.spec.ts#L152) checks if the transaction[ID:5] executed successfully.
-```
+![](/img/docs/writing-test-examples/test-examples-schemes_id5.svg)
-For the second fireworks contract:
+Transaction[ID:5] carries out in the Launcher with incoming message from the Fireworks launcher 1. This message sent with `send mode = 1`
```typescript
- it('should be correct op code for the launching second fireworks', async () => {
+ it('should exist a transaction[ID:5] with a comment send mode = 1', async() => {
const launcher = await blockchain.treasury('launcher');
const launchResult = await fireworks.sendDeployLaunch(
launcher.getSender(),
- toNano('3.5'),
+ toNano('2.5'),
);
- const init_code = code;
- const init_data = beginCell().storeUint(2, 32).endCell();
-
-
- const state_init = beginCell()
- .storeUint(0, 1) //no split_depth
- .storeUint(0, 1) // no special
- .storeUint(1, 1) // we have code
- .storeRef(init_code)
- .storeUint(1, 1) // we have data
- .storeRef(init_data)
- .storeUint(0, 1) // we have no library
- .endCell();
-
- const hash_dst = state_init.hash
- if (hash_dst === null) {
- throw Error("wrong type");
- }
-
-
- let launched_f2_address = new Address(0, hash_dst());
-
-
expect(launchResult.transactions).toHaveTransaction({
- from: fireworks.address,
- to: launched_f2_address,
- success: true,
- op: 0xa2e2c2dc, // 'launch_second' op code,
- outMessagesCount: 1
- });
-
- expect(launchResult.transactions).toHaveTransaction({
- from: launched_f2_address,
+ from: launched_f1.address,
to: launcher.address,
success: true,
- op: 0 // 0x00000000 - comment op code
+ body: beginCell().storeUint(0,32).storeStringTail("send mode = 1").endCell() // 0x00000000 comment opcode and encoded comment
});
- });
+ })
+
+
```
+### Transaction ID:6 Success Test
+
+[This test](https://github.com/ton-community/fireworks-func/blob/main/tests/Fireworks.spec.ts#L170) checks if the transaction[ID:6] executed successfully.
+
+![](/img/docs/writing-test-examples/test-examples-schemes_id6.svg)
-### Multi Transaction and Payload Tests
+The transaction[ID:6] carries out in the Launcher with incoming message from the Fireworks launcher 1. This message sent with `send mode = 2`
-This test checks if the fireworks contract sends multiple messages with comments correctly. The body field contains a Cell that is built with @ton/core primitives.
-#### For the first fireworks contract:
```typescript
- it('fireworks contract should send msgs with comments in first fireworks', async() => {
+ it('should exist a transaction[ID:6] with a comment send mode = 2', async() => {
const launcher = await blockchain.treasury('launcher');
const launchResult = await fireworks.sendDeployLaunch(
launcher.getSender(),
- toNano('3.5'),
+ toNano('2.5'),
);
- const init_code = code;
- const init_data = beginCell().storeUint(1, 32).endCell();
-
-
- const state_init = beginCell()
- .storeUint(0, 1) //no split_depth
- .storeUint(0, 1) // no special
- .storeUint(1, 1) // we have code
- .storeRef(init_code)
- .storeUint(1, 1) // we have data
- .storeRef(init_data)
- .storeUint(0, 1) // we have no library
- .endCell();
-
- const hash_dst = state_init.hash
- if (hash_dst === null) {
- throw Error("wrong type");
- }
-
-
- let launched_f1_address = new Address(0, hash_dst());
-
-
-
expect(launchResult.transactions).toHaveTransaction({
- from: launched_f1_address,
+ from: launched_f1.address,
to: launcher.address,
success: true,
- body: beginCell().storeUint(0,32).storeStringTail("send mode = 0").endCell() // 0x00000000 comment opcode and encoded comment
-
+ body: beginCell().storeUint(0,32).storeStringTail("send mode = 2").endCell() // 0x00000000 comment opcode and encoded comment
});
- expect(launchResult.transactions).toHaveTransaction({
- from: launched_f1_address,
- to: launcher.address,
- success: true,
- body: beginCell().storeUint(0,32).storeStringTail("send mode = 1").endCell()
- });
+ })
+```
- expect(launchResult.transactions).toHaveTransaction({
- from: launched_f1_address,
- to: launcher.address,
- success: true,
- body: beginCell().storeUint(0,32).storeStringTail("send mode = 2").endCell()
- });
+### Transaction ID:7 Success Test
- expect(launchResult.transactions).toHaveTransaction({
- from: launched_f1_address,
- to: launcher.address,
- success: true,
- body: beginCell().storeUint(0,32).storeStringTail("send mode = 32 + 128").endCell()
- });
- })
+[This test](https://github.com/ton-community/fireworks-func/blob/main/tests/Fireworks.spec.ts#L188) checks if the transaction[ID:7] executed successfully.
-```
+![](/img/docs/writing-test-examples/test-examples-schemes_id7.svg)
-#### For the second fireworks contract:
+The transaction[ID:7] carries out in the Launcher with incoming message from the Fireworks launcher 1. This message sent with `send mode = 128 + 32`
```typescript
- it('fireworks contract should send msgs with comments in second fireworks', async() => {
+ it('should exist a transaction[ID:7] with a comment send mode = 32 + 128', async() => {
const launcher = await blockchain.treasury('launcher');
const launchResult = await fireworks.sendDeployLaunch(
launcher.getSender(),
- toNano('3.5'),
+ toNano('2.5'),
);
- const init_code = code;
- const init_data = beginCell().storeUint(2, 32).endCell();
+ expect(launchResult.transactions).toHaveTransaction({
+ from: launched_f1.address,
+ to: launcher.address,
+ success: true,
+ body: beginCell().storeUint(0,32).storeStringTail("send mode = 32 + 128").endCell() // 0x00000000 comment opcode and encoded comment
+ });
+ })
+```
+### Transaction ID:8 Success Test
- const state_init = beginCell()
- .storeUint(0, 1) //no split_depth
- .storeUint(0, 1) // no special
- .storeUint(1, 1) // we have code
- .storeRef(init_code)
- .storeUint(1, 1) // we have data
- .storeRef(init_data)
- .storeUint(0, 1) // we have no library
- .endCell();
+[This test](https://github.com/ton-community/fireworks-func/blob/main/tests/Fireworks.spec.ts#L188) checks if the transaction[ID:8] executed successfully.
- const hash_dst = state_init.hash
- if (hash_dst === null) {
- throw Error("wrong type");
- }
+![](/img/docs/writing-test-examples/test-examples-schemes_id8.svg)
+The transaction[ID:8] carries out in the Launcher with incoming message from the Fireworks launcher 2. This message sent with `send mode = 64`
- let launched_f2_address = new Address(0, hash_dst());
+```typescript
+ it('should exist a transaction[ID:8] with a comment send mode = 64', async() => {
+ const launcher = await blockchain.treasury('launcher');
+ const launchResult = await fireworks.sendDeployLaunch(
+ launcher.getSender(),
+ toNano('2.5'),
+ );
expect(launchResult.transactions).toHaveTransaction({
- from: launched_f2_address,
+ from: launched_f2.address,
to: launcher.address,
success: true,
body: beginCell().storeUint(0,32).storeStringTail("send_mode = 64").endCell() // 0x00000000 comment opcode and encoded comment
@@ -483,23 +336,9 @@ This test checks if the fireworks contract sends multiple messages with comments
})
-
- it('should be executed and print fees', async() => {
-
- const launcher = await blockchain.treasury('launcher');
-
- const launchResult = await fireworks.sendDeployLaunch(
- launcher.getSender(),
- toNano('3.5'),
- );
-
- console.log(printTransactionFees(launchResult.transactions));
-
- });
-
```
-### Printing and Reading Transaction Fees
+## Printing and Reading Transaction Fees
During the test, reading the details about fees can be useful for optimizing the contract. The printTransactionFees function prints the entire transaction chain in a convenient manner."
```typescript
@@ -510,7 +349,7 @@ During the test, reading the details about fees can be useful for optimizing the
const launchResult = await fireworks.sendDeployLaunch(
launcher.getSender(),
- toNano('3.5'),
+ toNano('2.5'),
);
console.log(printTransactionFees(launchResult.transactions));
@@ -522,24 +361,21 @@ During the test, reading the details about fees can be useful for optimizing the
For instance, in case of `launchResult` the following table will be printed:
-
-
-
| (index) | op | valueIn | valueOut | totalFees | outActions |
|---------|--------------|----------------|----------------|----------------|------------|
-| 0 | 'N/A' | 'N/A' | '3.5 TON' | '0.010605 TON' | 1 |
-| 1 | '0x5720cfeb' | '3.5 TON' | '2.186786 TON' | '0.015386 TON' | 2 |
-| 2 | '0x6efe144b' | '1.093393 TON' | '1.081729 TON' | '0.008998 TON' | 4 |
-| 3 | '0xa2e2c2dc' | '1.093393 TON' | '1.089269 TON' | '0.003458 TON' | 1 |
+| 0 | 'N/A' | 'N/A' | '2.5 TON' | '0.010605 TON' | 1 |
+| 1 | '0x5720cfeb' | '2.5 TON' | '2.185812 TON' | '0.015836 TON' | 2 |
+| 2 | '0x6efe144b' | '1.092906 TON' | '1.081142 TON' | '0.009098 TON' | 4 |
+| 3 | '0xa2e2c2dc' | '1.092906 TON' | '1.088638 TON' | '0.003602 TON' | 1 |
| 4 | '0x0' | '0.099 TON' | '0 TON' | '0.000309 TON' | 0 |
| 5 | '0x0' | '0.1 TON' | '0 TON' | '0.000309 TON' | 0 |
| 6 | '0x0' | '0.099 TON' | '0 TON' | '0.000309 TON' | 0 |
-| 7 | '0x0' | '0.783729 TON' | '0 TON' | '0.000309 TON' | 0 |
-| 8 | '0x0' | '1.089269 TON' | '0 TON' | '0.000309 TON' | 0 |
+| 7 | '0x0' | '0.783142 TON' | '0 TON' | '0.000309 TON' | 0 |
+| 8 | '0x0' | '1.088638 TON' | '0 TON' | '0.000309 TON' | 0 |
-![](/img/docs/test-examples/fireworks_trace_tonviewer.png?=RAW)
+![](/img/docs/writing-test-examples/fireworks_trace_tonviewer.png?=RAW)
index - is an ID of a transaction in the `launchResult` array.
* `0` - External request to the treasury (the Launcher) that resulted in a message `op::set_first` to Fireworks
@@ -553,7 +389,7 @@ index - is an ID of a transaction in the `launchResult` array.
* `8` - Transaction on Launcher with incoming message from the Launched Fireworks - 2, message sent with `send mode = 64`
-### Transaction Fees Tests
+## Transaction Fees Tests
This test verifies whether the transaction fees for launching the fireworks are as expected. It is possible to define custom assertions for different parts of commission fees.
@@ -565,7 +401,7 @@ This test verifies whether the transaction fees for launching the fireworks are
const launchResult = await fireworks.sendDeployLaunch(
launcher.getSender(),
- toNano('3.5'),
+ toNano('2.5'),
);
//totalFee
@@ -598,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 -2256 < x < 2256 . 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/tvm-instructions/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).
+:::
diff --git a/docs/develop/smart-contracts/tutorials/wallet.md b/docs/develop/smart-contracts/tutorials/wallet.md
index a2fe1124ad..03fe849e5e 100644
--- a/docs/develop/smart-contracts/tutorials/wallet.md
+++ b/docs/develop/smart-contracts/tutorials/wallet.md
@@ -1,5 +1,5 @@
---
-description: In this tutorial, you will learn how to fully work with wallets, transactions and smart contracts.
+description: In this tutorial, you will learn how to fully work with wallets, messages and smart contracts.
---
import Tabs from '@theme/Tabs';
@@ -9,19 +9,19 @@ import TabItem from '@theme/TabItem';
## 👋 Introduction
-Learning how wallets and transactions work on TON before beginning smart contracts development is essential. This knowledge will help developers understand the interaction between wallets, transactions, and smart contracts to implement specific development tasks.
+Learning how wallets and transactions work on TON before beginning smart contracts development is essential. This knowledge will help developers understand the interaction between wallets, messages, and smart contracts to implement specific development tasks.
In this section we’ll learn to create operations without using pre-configured functions to understand development workflows. All references necessary for the analysis of this tutorial are located in the references chapter.
## 💡 Prerequisites
-This tutorial requires basic knowledge of Javascript, Typescript, and Golang. It is also necessary to hold at least 3 TON (which can be stored in an exchange account, a non-custodial wallet, or by using the telegram bot wallet). It is necessary to have a basic understanding of [cell](/learn/overviews/cells), [addresses in TON](/learn/overviews/addresses), [blockchain of blockchains](/learn/overviews/ton-blockchain) to understand this tutorial.
+This tutorial requires basic knowledge of Javascript and Typescript or Golang. It is also necessary to hold at least 3 TON (which can be stored in an exchange account, a non-custodial wallet, or by using the telegram bot wallet). It is necessary to have a basic understanding of [cell](/learn/overviews/cells), [addresses in TON](/learn/overviews/addresses), [blockchain of blockchains](/learn/overviews/ton-blockchain) to understand this tutorial.
:::info MAINNET DEVELOPMENT IS ESSENTIAL
Working with the TON Testnet often leads to deployment errors, difficulty tracking transactions, and unstable network functionality. Therefore, it could be beneficial to complete most development on the TON Mainnet to potentially avoid these issues, which might be necessary to reduce the number of transactions and thereby possibly minimize fees.
:::
-## Source Code
+## 💿 Source Code
All code examples used in this tutorial can be found in the following [GitHub repository](https://github.com/aSpite/wallet-tutorial).
@@ -54,10 +54,10 @@ go get github.com/xssnick/tonutils-go/address
## ⚙ Set Your Environment
-In order to create a TypeScript project its necessary to conduct the following steps in order:
+In order to create a TypeScript project it's necessary to conduct the following steps in order:
1. Create an empty folder (which we’ll name WalletsTutorial).
2. Open the project folder using the CLI.
-3. Use the followings commands to set up your project:
+3. Use the following commands to set up your project:
```bash
npm init -y
npm install typescript @types/node ts-node nodemon --save-dev
@@ -110,7 +110,7 @@ The TON Community created an excellent tool for automating all development proce
**OPTIONAL: ** When using Golang, follow these instructions::
1. Install the GoLand IDE.
-2. Create a project folder and `go.mod` file using the following content (the **version of Go** may need to be changed to conduct this process if the current version being used it outdated):
+2. Create a project folder and `go.mod` file using the following content (the **version of Go** may need to be changed to conduct this process if the current version being used is outdated):
```
module main
@@ -149,9 +149,9 @@ Additionally, only the imports required for a specific code section will be spec
## 🚀 Let's Get Started!
-In this tutorial we’ll learn which wallets (version’s 3 and 4) are most often used on TON Blockchain and get acquainted with how their smart contracts work. This will allow developers to better understand the different transaction types on the TON platform to make it simpler to create transactions, send them to the blockchain, deploy wallets, and eventually, be able to work with high-load wallets.
+In this tutorial we’ll learn which wallets (version’s 3 and 4) are most often used on TON Blockchain and get acquainted with how their smart contracts work. This will allow developers to better understand the different messages types on the TON platform to make it simpler to create messages, send them to the blockchain, deploy wallets, and eventually, be able to work with high-load wallets.
-Our main task is to build transactions using various objects and functions for @ton/ton, @ton/core, @ton/crypto (ExternalMessage, InternalMessage, Signing etc.) to understand what transactions look like on a bigger scale. To carry out this process we'll make use of two main wallet versions (v3 and v4) because of the fact that exchanges, non-custodial wallets, and most users only used these specific versions.
+Our main task is to build messages using various objects and functions for @ton/ton, @ton/core, @ton/crypto (ExternalMessage, InternalMessage, Signing etc.) to understand what messages look like on a bigger scale. To carry out this process we'll make use of two main wallet versions (v3 and v4) because of the fact that exchanges, non-custodial wallets, and most users only used these specific versions.
:::note
There may be occasions in this tutorial when there is no explanation for particular details. In these cases, more details will be provided in later stages of this tutorial.
@@ -165,21 +165,21 @@ All wallets that operate and run on TON Blockchain are actually smart contracts,
On TON wallet smart contracts help the platform communicate with other smart contract types. However, it is important to consider how wallet communication takes place.
### Wallet Communication
-Generally, there are two transaction types on TON Blockchain: `internal` and `external`. External transactions allow for the ability to send messages to the blockchain from the outside world, thus allowing for the communication with smart contracts that accept such transactions. The function responsible for carrying out this process is as follows:
+Generally, there are two message types on TON Blockchain: `internal` and `external`. External messages allow for the ability to send messages to the blockchain from the outside world, thus allowing for the communication with smart contracts that accept such messages. The function responsible for carrying out this process is as follows:
```func
() recv_external(slice in_msg) impure {
;; some code
}
```
-Before we dive into more details concerning wallets, let’s look at how wallets accept external transactions. On TON, all wallets hold the owner’s `public key`, `seqno`, and `subwallet_id`. When receiving an external transaction, the wallet uses the `get_data()` method to retrieve data from the storage portion of the wallet. It then conducts several verification procedures and decides whether to accept the transaction or not. This process is conducted as follows:
+Before we dive into more details concerning wallets, let’s look at how wallets accept external messages. On TON, all wallets hold the owner’s `public key`, `seqno`, and `subwallet_id`. When receiving an external message, the wallet uses the `get_data()` method to retrieve data from the storage portion of the wallet. It then conducts several verification procedures and decides whether to accept the message or not. This process is conducted as follows:
```func
() recv_external(slice in_msg) impure {
var signature = in_msg~load_bits(512); ;; get signature from the message body
var cs = in_msg;
var (subwallet_id, valid_until, msg_seqno) = (cs~load_uint(32), cs~load_uint(32), cs~load_uint(32)); ;; get rest values from the message body
- throw_if(35, valid_until <= now()); ;; check the relevance of the transaction
+ throw_if(35, valid_until <= now()); ;; check the relevance of the message
var ds = get_data().begin_parse(); ;; get data from storage and convert it into a slice to be able to read values
var (stored_seqno, stored_subwallet, public_key) = (ds~load_uint(32), ds~load_uint(32), ds~load_uint(256)); ;; read values from storage
ds.end_parse(); ;; make sure we do not have anything in ds variable
@@ -213,13 +213,13 @@ Now let’s take a closer look.
### Replay Protection - Seqno
-Transaction replay protection in the wallet smart contract is directly related to the transaction seqno (Sequence Number) which keeps track of which transactions are sent in which order. It is very important that a single transaction is not repeated from a wallet because it throws off the integrity of the system entirely. If we further examine smart contract code within a wallet, the `seqno` is typically handled as follows:
+Message replay protection in the wallet smart contract is directly related to the message seqno (Sequence Number) which keeps track of which messages are sent in which order. It is very important that a single message is not repeated from a wallet because it throws off the integrity of the system entirely. If we further examine smart contract code within a wallet, the `seqno` is typically handled as follows:
```func
throw_unless(33, msg_seqno == stored_seqno);
```
-This line of code above checks the `seqno`, which comes in the transaction and checks it with `seqno`, which is stored in a smart contract. The contract returns an error with `33 exit code` if they do not match. So if the sender passed invalid seqno, it means that he made some mistake in the transaction sequence, and the contract protects against such cases.
+This line of code above checks the `seqno`, which comes in the message and checks it with `seqno`, which is stored in a smart contract. The contract returns an error with `33 exit code` if they do not match. So if the sender passed invalid seqno, it means that he made some mistake in the message sequence, and the contract protects against such cases.
:::note
It's also essential to consider that external messages can be sent by anyone. This means that if you send 1 TON to someone, someone else can repeat this message. However, when the seqno increases, the previous external message becomes invalid, and no one will be able to repeat it, thus preventing the possibility of stealing your funds.
@@ -227,7 +227,7 @@ It's also essential to consider that external messages can be sent by anyone. Th
### Signature
-As mentioned earlier, wallet smart contracts accept external transactions. However, these transactions come from the outside world and that data cannot be 100% trusted. Therefore, each wallet stores the owner's public key. The smart contract uses a public key to verify the legitimacy of the transaction signature when receiving an external transaction that the owner signed with the private key. This verifies that the transaction is actually from the contract owner.
+As mentioned earlier, wallet smart contracts accept external messages. However, these messages come from the outside world and that data cannot be 100% trusted. Therefore, each wallet stores the owner's public key. The smart contract uses a public key to verify the legitimacy of the message signature when receiving an external message that the owner signed with the private key. This verifies that the message is actually from the contract owner.
To carry out this process, the wallet must first obtain the signature from the incoming message which loads the public key from storage and validates the signature using the following process:
@@ -245,19 +245,19 @@ accept_message();
```
:::info accept_message()
-Because the transaction comes from the outside world, it does not contain the Toncoin required to pay the transaction fee. When sending TON using the accept_message() function, a gas_credit (at the time of writing its value is 10,000 gas units) is applied which allows the necessary calculations to be carried out for free if the gas does not exceed the gas_credit value. After the accept_message() function is used, all the gas spent (in TON) is taken from the balance of the smart contract. More can be read about this process [here](/develop/smart-contracts/guidelines/accept).
+Because the message comes from the outside world, it does not contain the Toncoin required to pay the transaction fee. When sending TON using the accept_message() function, a gas_credit (at the time of writing its value is 10,000 gas units) is applied which allows the necessary calculations to be carried out for free if the gas does not exceed the gas_credit value. After the accept_message() function is used, all the gas spent (in TON) is taken from the balance of the smart contract. More can be read about this process [here](/develop/smart-contracts/guidelines/accept).
:::
### Transaction Expiration
-Another step used to check the validity of external transactions is the `valid_until` field. As you can see from the variable name, this is the time in UNIX before the transaction is valid. If this verification process fails, the contract completes the processing of the transaction and returns the 32 exit code follows:
+Another step used to check the validity of external messages is the `valid_until` field. As you can see from the variable name, this is the time in UNIX before the message is valid. If this verification process fails, the contract completes the processing of the transaction and returns the 35 exit code follows:
```func
var (subwallet_id, valid_until, msg_seqno) = (cs~load_uint(32), cs~load_uint(32), cs~load_uint(32));
throw_if(35, valid_until <= now());
```
-This algorithm works to protect against the susceptibility of various errors when the transaction is no longer valid but was still sent to the blockchain for an unknown reason.
+This algorithm works to protect against the susceptibility of various errors when the message is no longer valid but was still sent to the blockchain for an unknown reason.
### Wallet v3 and Wallet v4 Differences
@@ -267,13 +267,13 @@ Wallet smart contracts, in turn, will send the required amount of TON in respons
### How Wallets facilitate communication with Smart Contracts
-As we discussed earlier, a wallet smart contract accepts external transactions, validates them and accepts them if all checks are passed. The contract then starts the loop of retrieving messages from the body of external messages then creates internal messages and sends them to the blockchain as follows:
+As we discussed earlier, a wallet smart contract accepts external messages, validates them and accepts them if all checks are passed. The contract then starts the loop of retrieving messages from the body of external messages then creates internal messages and sends them to the blockchain as follows:
```func
cs~touch();
while (cs.slice_refs()) {
- var mode = cs~load_uint(8); ;; load transaction mode
+ var mode = cs~load_uint(8); ;; load message mode
send_raw_message(cs~load_ref(), mode); ;; get each new internal message as a cell with the help of load_ref() and send it
}
```
@@ -288,19 +288,19 @@ Since a **maximum of 4 references** can be stored in one cell, we can send a max
>
> ["slice_refs()" in docs](/develop/func/stdlib/#slice_refs)
>
-> ["send_raw_message() and transaction modes" in docs](/develop/func/stdlib/#send_raw_message)
+> ["send_raw_message() and message modes" in docs](/develop/func/stdlib/#send_raw_message)
>
> ["load_ref()" in docs](/develop/func/stdlib/#load_ref)
-## 📬 External and Internal Transactions
+## 📬 External and Internal Messages
-In this section, we’ll learn more about `internal` and `external` transactions and we’ll create transactions and send them to the network to minimize the use of pre-cooked functions.
+In this section, we’ll learn more about `internal` and `external` messages and we’ll create messages and send them to the network to minimize the use of pre-cooked functions.
To carry out this process it is necessary to make use of a ready-made wallet to make the task easier. To accomplish this:
1. Install the [wallet app](/participate/wallets/apps) (e.g., Tonkeeper is used by the author)
2. Switch wallet app to v3r2 address version
3. Deposit 1 TON into the wallet
-4. Send the transaction to another address (you can send to yourself, to the same wallet).
+4. Send the message to another address (you can send to yourself, to the same wallet).
This way, the Tonkeeper wallet app will deploy the wallet contract and we can use it for the following steps.
@@ -312,7 +312,7 @@ At the time of writing, most wallet apps on TON by default use the wallet v4 ver
As noted, everything in TON Blockchain is a smart contract consisting of cells. To properly serialize and deserialize the data we need standards. To accomplish the serialization and deserialization process, `TL-B` was created as a universal tool to describe different data types in different ways with different sequences inside cells.
-In this section, we’ll examine [block.tlb](https://github.com/ton-blockchain/ton/blob/master/crypto/block/block.tlb). This file will be very useful during future development, as it describes how different cells should be assembled. In our case specifically, it details the intricacies of internal and external transactions.
+In this section, we’ll examine [block.tlb](https://github.com/ton-blockchain/ton/blob/master/crypto/block/block.tlb). This file will be very useful during future development, as it describes how different cells should be assembled. In our case specifically, it details the intricacies of internal and external messages.
:::info
Basic information will be provided within this guide. For further details, please refer to our TL-B [documentation](/develop/data-formats/tl-b-language) to learn more about TL-B.
@@ -320,12 +320,12 @@ Basic information will be provided within this guide. For further details, pleas
### CommonMsgInfo
-Initially, each message must first store `CommonMsgInfo` ([TL-B](https://github.com/ton-blockchain/ton/blob/24dc184a2ea67f9c47042b4104bbb4d82289fac1/crypto/block/block.tlb#L123-L130)) or `CommonMsgInfoRelaxed` ([TL-B](https://github.com/ton-blockchain/ton/blob/24dc184a2ea67f9c47042b4104bbb4d82289fac1/crypto/block/block.tlb#L132-L137)). This allows us to define technical details that relate to the transaction type, transaction time, recipient address, technical flags, and fees.
+Initially, each message must first store `CommonMsgInfo` ([TL-B](https://github.com/ton-blockchain/ton/blob/24dc184a2ea67f9c47042b4104bbb4d82289fac1/crypto/block/block.tlb#L123-L130)) or `CommonMsgInfoRelaxed` ([TL-B](https://github.com/ton-blockchain/ton/blob/24dc184a2ea67f9c47042b4104bbb4d82289fac1/crypto/block/block.tlb#L132-L137)). This allows us to define technical details that relate to the message type, message time, recipient address, technical flags, and fees.
-By reading `block.tlb` file, we can notice three types of CommonMsgInfo: `int_msg_info$0`, `ext_in_msg_info$10`, `ext_out_msg_info$11`. We will not go into specific details detailing the specificities of the `ext_out_msg_info` TL-B structure. That said, it is an external transaction type that a smart contract can send for using as external logs. For examples of this format, consider having a closer look at the [Elector]((https://tonscan.org/address/Ef8zMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzM0vF)) contract.
+By reading `block.tlb` file, we can notice three types of CommonMsgInfo: `int_msg_info$0`, `ext_in_msg_info$10`, `ext_out_msg_info$11`. We will not go into specific details detailing the specificities of the `ext_out_msg_info` TL-B structure. That said, it is an external message type that a smart contract can send for using as external logs. For examples of this format, consider having a closer look at the [Elector]((https://tonscan.org/address/Ef8zMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzM0vF)) contract.
-[Looking at TL-B](https://github.com/ton-blockchain/ton/blob/24dc184a2ea67f9c47042b4104bbb4d82289fac1/crypto/block/block.tlb#L127-L128), you’ll notice that **only the CommonMsgInfo is available when used with the ext_in_msg_info type**. This is because transaction type fields such as `src`, `created_lt`, `created_at`, and others are rewritten by validators during transaction handling. In this case, the `src` transaction type is most important because when transactions are sent, the sender is unknown, and is written by validators during verification. This ensures that the address in the `src` field is correct and cannot be manipulated.
+[Looking at TL-B](https://github.com/ton-blockchain/ton/blob/24dc184a2ea67f9c47042b4104bbb4d82289fac1/crypto/block/block.tlb#L127-L128), you’ll notice that **only the CommonMsgInfo is available when used with the ext_in_msg_info type**. This is because message fields such as `src`, `created_lt`, `created_at`, and others are rewritten by validators during transaction handling. In this case, the `src` field in message is most important because when messages are sent, the sender is unknown, and is written by validators during verification. This ensures that the address in the `src` field is correct and cannot be manipulated.
However, the `CommonMsgInfo` structure only supports the `MsgAddress` specification, but the sender’s address is typically unknown and it is required to write the `addr_none` (two zero bits `00`). In this case, the `CommonMsgInfoRelaxed` structure is used, which supports the `addr_none` address. For the `ext_in_msg_info` (used for incoming external messages), the `CommonMsgInfo` structure is used because these message types don’t make use of a sender and always use the [MsgAddressExt](https://hub.com/ton/ton.blockchain/ton/blob/24dc184a2ea67f9c47042b4104bbb4d82289fac1/crypto/block/block.tlb#L100) structure (the `addr_none$00` meaning two zero bits), which means there is no need to overwrite the data.
@@ -333,16 +333,16 @@ However, the `CommonMsgInfo` structure only supports the `MsgAddress` specificat
The numbers after `$` symbol are the bits that are required to store at the beginning of a certain structure, for further identification of these structures during reading (deserialization).
:::
-### Internal Transaction Creation
+### Internal Message Creation
-Internal transactions are used to send messages between contracts. When analyzing various contract types (such as [NFTs](https://github.com/ton-blockchain/token-contract/blob/f2253cb0f0e1ae0974d7dc0cef3a62cb6e19f806/nft/nft-item.fc#L51-L56) and [Jetons](https://github.com/ton-blockchain/token-contract/blob/f2253cb0f0e1ae0974d7dc0cef3a62cb6e19f806/ft/jetton-wallet.fc#L139-L144)) that send messages where the writing of contracts is considered, the following lines of code are often used:
+Internal messages are used to send messages between contracts. When analyzing various contract types (such as [NFTs](https://github.com/ton-blockchain/token-contract/blob/f2253cb0f0e1ae0974d7dc0cef3a62cb6e19f806/nft/nft-item.fc#L51-L56) and [Jetons](https://github.com/ton-blockchain/token-contract/blob/f2253cb0f0e1ae0974d7dc0cef3a62cb6e19f806/ft/jetton-wallet.fc#L139-L144)) that send messages where the writing of contracts is considered, the following lines of code are often used:
```func
var msg = begin_cell()
.store_uint(0x18, 6) ;; or 0x10 for non-bounce
.store_slice(to_address)
.store_coins(amount)
- .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1)
+ .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1) ;; default message headers (see sending messages page)
;; store something as a body
```
@@ -357,7 +357,7 @@ var msg = begin_cell()
.store_uint(0, 2) ;; src -> two zero bits for addr_none
.store_slice(to_address)
.store_coins(amount)
- .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1)
+ .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1) ;; default message headers (see sending messages page)
;; store something as a body
```
Now let’s go through each option in detail:
@@ -365,8 +365,8 @@ Now let’s go through each option in detail:
Option | Explanation
:---: | :---:
IHR Disabled | Currently, this option is disabled (which means we store 1) because Instant Hypercube Routing is not fully implemented. In addition, this will be needed when a large number of [Shardchains](/learn/overviews/ton-blockchain#many-accountchains-shards) are live on the network. More can be read about the IHR Disabled option in the [tblkch.pdf](https://ton.org/tblkch.pdf) (chapter 2).
-Bounce | While sending transactions, a variety of errors can occur during smart contract processing. To avoid losing TON, it is necessary to set the Bounce option to 1 (true). In this case, if any contract errors occur during transaction processing, the transaction will be returned to the sender, and the same amount of TON will be received minus fees. More can be read about non-bounceable messages [here](/develop/smart-contracts/guidelines/non-bouncable-messages).
-Bounced | Bounced transactions are transactions that are returned to the sender because an error occurred while processing the transaction with a smart contract. This option tells you whether the transaction received is bounced or not.
+Bounce | While sending messages, a variety of errors can occur during smart contract processing. To avoid losing TON, it is necessary to set the Bounce option to 1 (true). In this case, if any contract errors occur during transaction processing, the message will be returned to the sender, and the same amount of TON will be received minus fees. More can be read about non-bounceable messages [here](/develop/smart-contracts/guidelines/non-bouncable-messages).
+Bounced | Bounced messages are messages that are returned to the sender because an error occurred while processing the transaction with a smart contract. This option tells you whether the message received is bounced or not.
Src | The Src is the sender address. In this case, two zero bits are written to indicate the `addr_none` address.
The next two lines of code:
@@ -396,8 +396,8 @@ Option | Explanation
Extra currency | This is a native implementation of existing jettons and is not currently in use.
IHR fee | As mentioned, the IHR is not currently in use, so this fee is always zero. More can be read about this in the [tblkch.pdf](https://ton.org/tblkch.pdf) (3.1.8).
Forwarding fee | A forwarding message fee. More can be read about this in the [fees documentation](/develop/howto/fees-low-level#transactions-and-phases).
-Logical time of creation | The time used to create the correct transaction queue.
-UNIX tome of creation | The time the transaction was created in UNIX.
+Logical time of creation | The time used to create the correct messages queue.
+UNIX time of creation | The time the message was created in UNIX.
State Init | Code and source data for deploying a smart contract. If the bit is set to `0`, it means that we do not have a State Init. But if it is set to `1`, then another bit needs to be written which indicates whether the State Init is stored in the same cell (0) or written as a reference (1).
Message body | This part defines how the message body is stored. At times the message body is too large to fit into the message itself. In this case, it should be stored as a **reference** whereby the bit is set to `1` to show that the body is used as a reference. If the bit is `0`, the body is in the same cell as the message.
@@ -407,7 +407,7 @@ The values outlined above (including src) excluding the State Init and the Messa
If the number value fits within fewer bits than is specified, then the missing zeros are added to the left side of the value. For example, 0x18 fits within 5 bits -> `11000`. However, since 6 bits were specified, the end result becomes `011000`.
:::
-Next, we’ll begin preparing a transaction, which will be sent Toncoins to another wallet v3.
+Next, we’ll begin preparing a message, which will be sent Toncoins to another wallet v3.
First, let’s say a user wants to send 0.5 TON to themselves with the text "**Hello, TON!**", refer to this section of our documentation to learn ([How to send message with a comment](/develop/func/cookbook#how-to-send-a-simple-message)).
@@ -416,10 +416,10 @@ First, let’s say a user wants to send 0.5 TON to themselves with the text "**H
```js
import { beginCell } from '@ton/core';
-let internalMessageBody = beginCell().
- storeUint(0, 32). // write 32 zero bits to indicate that a text comment will follow
- storeStringTail("Hello, TON!"). // write our text comment
- endCell();
+let internalMessageBody = beginCell()
+ .storeUint(0, 32) // write 32 zero bits to indicate that a text comment will follow
+ .storeStringTail("Hello, TON!") // write our text comment
+ .endCell();
```
@@ -451,23 +451,23 @@ import { toNano, Address } from '@ton/ton';
const walletAddress = Address.parse('put your wallet address');
-let internalMessage = beginCell().
- storeUint(0, 1). // indicate that it is an internal message -> int_msg_info$0
- storeBit(1). // IHR Disabled
- storeBit(1). // bounce
- storeBit(0). // bounced
- storeUint(0, 2). // src -> addr_none
- storeAddress(walletAddress).
- storeCoins(toNano("0.2")). // amount
- storeBit(0). // Extra currency
- storeCoins(0). // IHR Fee
- storeCoins(0). // Forwarding Fee
- storeUint(0, 64). // Logical time of creation
- storeUint(0, 32). // UNIX time of creation
- storeBit(0). // No State Init
- storeBit(1). // We store Message Body as a reference
- storeRef(internalMessageBody). // Store Message Body as a reference
- endCell();
+let internalMessage = beginCell()
+ .storeUint(0, 1) // indicate that it is an internal message -> int_msg_info$0
+ .storeBit(1) // IHR Disabled
+ .storeBit(1) // bounce
+ .storeBit(0) // bounced
+ .storeUint(0, 2) // src -> addr_none
+ .storeAddress(walletAddress)
+ .storeCoins(toNano("0.2")) // amount
+ .storeBit(0) // Extra currency
+ .storeCoins(0) // IHR Fee
+ .storeCoins(0) // Forwarding Fee
+ .storeUint(0, 64) // Logical time of creation
+ .storeUint(0, 32) // UNIX time of creation
+ .storeBit(0) // No State Init
+ .storeBit(1) // We store Message Body as a reference
+ .storeRef(internalMessageBody) // Store Message Body as a reference
+ .endCell();
```
@@ -505,7 +505,7 @@ internalMessage := cell.BeginCell().
### Creating a Message
-It is necessary to retrieve the `seqno` (sequence number) of our wallet smart contract. To accomplish this, a `Client` is created which will be used to send a request to run the Get method "seqno" of our wallet. It is also necessary to add a seed phrase (which you saved during creating a wallet [here](#--external-and-internal-transactions)) to sign our transaction via the following steps:
+It is necessary to retrieve the `seqno` (sequence number) of our wallet smart contract. To accomplish this, a `Client` is created which will be used to send a request to run the Get method "seqno" of our wallet. It is also necessary to add a seed phrase (which you saved during creating a wallet [here](#--external-and-internal-messages)) to sign our message via the following steps:
@@ -585,19 +585,19 @@ Therefore, the `seqno`, `keys`, and `internal message` need to be sent. Now we n
```js
import { sign } from '@ton/crypto';
-let toSign = beginCell().
- storeUint(698983191, 32). // subwallet_id | We consider this further
- storeUint(Math.floor(Date.now() / 1e3) + 60, 32). // Transaction expiration time, +60 = 1 minute
- storeUint(seqno, 32). // store seqno
- storeUint(3, 8). // store mode of our internal transaction
- storeRef(internalMessage); // store our internalMessage as a reference
+let toSign = beginCell()
+ .storeUint(698983191, 32) // subwallet_id | We consider this further
+ .storeUint(Math.floor(Date.now() / 1e3) + 60, 32) // Message expiration time, +60 = 1 minute
+ .storeUint(seqno, 32) // store seqno
+ .storeUint(3, 8) // store mode of our internal message
+ .storeRef(internalMessage); // store our internalMessage as a reference
let signature = sign(toSign.endCell().hash(), keyPair.secretKey); // get the hash of our message to wallet smart contract and sign it to get signature
-let body = beginCell().
- storeBuffer(signature). // store signature
- storeBuilder(toSign). // store our message
- endCell();
+let body = beginCell()
+ .storeBuffer(signature) // store signature
+ .storeBuilder(toSign) // store our message
+ .endCell();
```
@@ -610,9 +610,9 @@ import (
toSign := cell.BeginCell().
MustStoreUInt(698983191, 32). // subwallet_id | We consider this further
- MustStoreUInt(uint64(time.Now().UTC().Unix()+60), 32). // Transaction expiration time, +60 = 1 minute
+ MustStoreUInt(uint64(time.Now().UTC().Unix()+60), 32). // Message expiration time, +60 = 1 minute
MustStoreUInt(seqno.Uint64(), 32). // store seqno
- MustStoreUInt(uint64(3), 8). // store mode of our internal transaction
+ MustStoreUInt(uint64(3), 8). // store mode of our internal message
MustStoreRef(internalMessage) // store our internalMessage as a reference
signature := ed25519.Sign(privateKey, toSign.EndCell().Hash()) // get the hash of our message to wallet smart contract and sign it to get signature
@@ -630,26 +630,26 @@ Note that here no `.endCell()` was used in the definition of the `toSign`. The f
:::tip Wallet V4
-In addition to basic verification process we learned bellow for the Wallet V3, Wallet V4 smart contracts [extracts the opcode to determine whether a simple translation or a transaction associated with the plugin](https://github.com/ton-blockchain/wallet-contract/blob/4111fd9e3313ec17d99ca9b5b1656445b5b49d8f/func/wallet-v4-code.fc#L94-L100) is required. To match this version, it is necessary to add the `storeUint(0, 8).` (JS/TS), `MustStoreUInt(0, 8).` (Golang) functions after writing the seqno (sequence number) and before specifying the transaction mode.
+In addition to basic verification process we learned bellow for the Wallet V3, Wallet V4 smart contracts [extracts the opcode to determine whether a simple translation or a message associated with the plugin](https://github.com/ton-blockchain/wallet-contract/blob/4111fd9e3313ec17d99ca9b5b1656445b5b49d8f/func/wallet-v4-code.fc#L94-L100) is required. To match this version, it is necessary to add the `storeUint(0, 8).` (JS/TS), `MustStoreUInt(0, 8).` (Golang) functions after writing the seqno (sequence number) and before specifying the transaction mode.
:::
-### External Transaction Creation
+### External Message Creation
-To deliver any internal message to a blockchain from the outside world, it is necessary to send it within an external transaction. As we have previously considered, it is necessary to only make use of the `ext_in_msg_info$10` structure, as the goal is to send an external message to our contract. Now, let's create an external message that will be sent to our wallet:
+To deliver any internal message to a blockchain from the outside world, it is necessary to send it within an external message. As we have previously considered, it is necessary to only make use of the `ext_in_msg_info$10` structure, as the goal is to send an external message to our contract. Now, let's create an external message that will be sent to our wallet:
```js
-let externalMessage = beginCell().
- storeUint(0b10, 2). // 0b10 -> 10 in binary
- storeUint(0, 2). // src -> addr_none
- storeAddress(walletAddress). // Destination address
- storeCoins(0). // Import Fee
- storeBit(0). // No State Init
- storeBit(1). // We store Message Body as a reference
- storeRef(body). // Store Message Body as a reference
- endCell();
+let externalMessage = beginCell()
+ .storeUint(0b10, 2) // 0b10 -> 10 in binary
+ .storeUint(0, 2) // src -> addr_none
+ .storeAddress(walletAddress) // Destination address
+ .storeCoins(0) // Import Fee
+ .storeBit(0) // No State Init
+ .storeBit(1) // We store Message Body as a reference
+ .storeRef(body) // Store Message Body as a reference
+ .endCell();
```
@@ -719,13 +719,13 @@ if err != nil {
>
> [More about Bag of Cells](/develop/data-formats/cell-boc#bag-of-cells)
-As a result, we got the output of our BOC in the console and the transaction sent to our wallet. By copying the base64 encoded string, it is possible to [manually send our transaction and retrieve the hash using toncenter](https://toncenter.com/api/v2/#/send/send_boc_return_hash_sendBocReturnHash_post).
+As a result, we got the output of our BOC in the console and the message sent to our wallet. By copying the base64 encoded string, it is possible to [manually send our message and retrieve the hash using toncenter](https://toncenter.com/api/v2/#/send/send_boc_return_hash_sendBocReturnHash_post).
## 👛 Deploying a Wallet
We have learned the basics of creating messages, which will now be helpful for deploying the wallet. In the past, we have deployed wallet via wallet app, but in this case we’ll need to deploy our wallet manually.
-In this section we’ll go over how to create a wallet (wallet v3) from scratch. You’ll learn how to compile the code for a wallet smart contract, generate a mnemonic phrase, receive a wallet address, and deploy a wallet using external transactions and State Init (state initialization).
+In this section we’ll go over how to create a wallet (wallet v3) from scratch. You’ll learn how to compile the code for a wallet smart contract, generate a mnemonic phrase, receive a wallet address, and deploy a wallet using external messages and State Init (state initialization).
### Generating a Mnemonic
@@ -778,7 +778,7 @@ log.Println(mnemonic) // if we want, we can print our mnemonic
-The private key is needed to sign transactions and the public key is stored in the wallet’s smart contract.
+The private key is needed to sign messages and the public key is stored in the wallet’s smart contract.
:::danger IMPORTANT
It is necessary to output the generated mnemonic seed phrase to the console then save and use it (as detailed in the previous section) in order to use the same key pair each time the wallet’s code is run.
@@ -798,7 +798,7 @@ res.wallet_id = td::as(res.config.zero_state_id.root_hash.as_slice()
It is possible to retrieve genesis block information (zero_state) from the [configuration file](https://ton.org/global-config.json). Understanding the complexities and details of this is not necessary but it's important to remember that the default value of the `subwallet_id` is `698983191`.
-Each wallet contract checks the subwallet_id field for external transactions to avoid instances when requests were sent to wallet with another ID:
+Each wallet contract checks the subwallet_id field for external messages to avoid instances when requests were sent to wallet with another ID:
```func
var (subwallet_id, valid_until, msg_seqno) = (cs~load_uint(32), cs~load_uint(32), cs~load_uint(32));
@@ -936,7 +936,7 @@ After the above processes are complete it is confirmed that the correct code is
### Creating the State Init for Deployment
-Before building a transaction it is important to understand what a State Init is. First let’s go through the [TL-B scheme](https://github.com/ton-blockchain/ton/blob/24dc184a2ea67f9c47042b4104bbb4d82289fac1/crypto/block/block.tlb#L141-L143):
+Before building a message it is important to understand what a State Init is. First let’s go through the [TL-B scheme](https://github.com/ton-blockchain/ton/blob/24dc184a2ea67f9c47042b4104bbb4d82289fac1/crypto/block/block.tlb#L141-L143):
Option | Explanation
:---: | :---:
@@ -954,11 +954,11 @@ Next we’ll prepare the `initial data`, which will be present in our contract
```js
import { beginCell } from '@ton/core';
-const dataCell = beginCell().
- storeUint(0, 32). // Seqno
- storeUint(698983191, 32). // Subwallet ID
- storeBuffer(keyPair.publicKey). // Public Key
- endCell();
+const dataCell = beginCell()
+ .storeUint(0, 32) // Seqno
+ .storeUint(698983191, 32) // Subwallet ID
+ .storeBuffer(keyPair.publicKey) // Public Key
+ .endCell();
```
@@ -983,15 +983,15 @@ At this stage, both the contract `code` and its `initial data` is present. With
```js
import { Address } from '@ton/core';
-const stateInit = beginCell().
- storeBit(0). // No split_depth
- storeBit(0). // No special
- storeBit(1). // We have code
- storeRef(codeCell).
- storeBit(1). // We have data
- storeRef(dataCell).
- storeBit(0). // No library
- endCell();
+const stateInit = beginCell()
+ .storeBit(0) // No split_depth
+ .storeBit(0) // No special
+ .storeBit(1) // We have code
+ .storeRef(codeCell)
+ .storeBit(1) // We have data
+ .storeRef(dataCell)
+ .storeBit(0) // No library
+ .endCell();
const contractAddress = new Address(0, stateInit.hash()); // get the hash of stateInit to get the address of our smart contract in workchain with ID 0
console.log(`Contract address: ${contractAddress.toString()}`); // Output contract address to console
@@ -1022,9 +1022,9 @@ log.Println("Contract address:", contractAddress.String()) // Output contract ad
-Using the State Init, we can now build the transaction and send it to the blockchain. To carry out this process **a minimum wallet balance of 0.1 TON** (the balance can be less, but this amount is guaranteed to be sufficient) is required. To accomplish this, we’ll need to run the code mentioned earlier in the tutorial, get the correct wallet address and send 0.1 TON to this address.
+Using the State Init, we can now build the message and send it to the blockchain. To carry out this process **a minimum wallet balance of 0.1 TON** (the balance can be less, but this amount is guaranteed to be sufficient) is required. To accomplish this, we’ll need to run the code mentioned earlier in the tutorial, get the correct wallet address and send 0.1 TON to this address.
-Let’s start with building the transaction similar to the one we built **in the previous section**:
+Let’s start with building the message similar to the one we built **in the previous section**:
@@ -1033,32 +1033,32 @@ Let’s start with building the transaction similar to the one we built **in the
import { sign } from '@ton/crypto';
import { toNano } from '@ton/core';
-const internalMessageBody = beginCell().
- storeUint(0, 32).
- storeStringTail("Hello, TON!").
- endCell();
-
-const internalMessage = beginCell().
- storeUint(0x10, 6). // no bounce
- storeAddress(Address.parse("put your first wallet address from were you sent 0.1 TON")).
- storeCoins(toNano("0.03")).
- storeUint(1, 1 + 4 + 4 + 64 + 32 + 1 + 1). // We store 1 that means we have body as a reference
- storeRef(internalMessageBody).
- endCell();
-
-// transaction for our wallet
-const toSign = beginCell().
- storeUint(subWallet, 32).
- storeUint(Math.floor(Date.now() / 1e3) + 60, 32).
- storeUint(0, 32). // We put seqno = 0, because after deploying wallet will store 0 as seqno
- storeUint(3, 8).
- storeRef(internalMessage);
+const internalMessageBody = beginCell()
+ .storeUint(0, 32)
+ .storeStringTail("Hello, TON!")
+ .endCell();
+
+const internalMessage = beginCell()
+ .storeUint(0x10, 6) // no bounce
+ .storeAddress(Address.parse("put your first wallet address from were you sent 0.1 TON"))
+ .storeCoins(toNano("0.03"))
+ .storeUint(1, 1 + 4 + 4 + 64 + 32 + 1 + 1) // We store 1 that means we have body as a reference
+ .storeRef(internalMessageBody)
+ .endCell();
+
+// message for our wallet
+const toSign = beginCell()
+ .storeUint(subWallet, 32)
+ .storeUint(Math.floor(Date.now() / 1e3) + 60, 32)
+ .storeUint(0, 32) // We put seqno = 0, because after deploying wallet will store 0 as seqno
+ .storeUint(3, 8)
+ .storeRef(internalMessage);
const signature = sign(toSign.endCell().hash(), keyPair.secretKey);
-const body = beginCell().
- storeBuffer(signature).
- storeBuilder(toSign).
- endCell();
+const body = beginCell()
+ .storeBuffer(signature)
+ .storeBuilder(toSign)
+ .endCell();
```
@@ -1083,7 +1083,7 @@ internalMessage := cell.BeginCell().
MustStoreRef(internalMessageBody).
EndCell()
-// transaction for our wallet
+// message for our wallet
toSign := cell.BeginCell().
MustStoreUInt(subWallet, 32).
MustStoreUInt(uint64(time.Now().UTC().Unix()+60), 32).
@@ -1103,7 +1103,7 @@ body := cell.BeginCell().
After this is completed the result is the correct State Init and Message Body.
-### Sending An External Transaction
+### Sending An External Message
The **main difference** will be in the presence of the external message, because the State Init is stored to help carry out correct contract deployment. Since the contract does not have its own code yet, it cannot process any internal messages. Therefore, next we send its code and the initial data **after it is successfully deployed so it can process our message** with "Hello, TON!" comment:
@@ -1111,17 +1111,17 @@ The **main difference** will be in the presence of the external message, because
```js
-const externalMessage = beginCell().
- storeUint(0b10, 2). // indicate that it is an incoming external transaction
- storeUint(0, 2). // src -> addr_none
- storeAddress(contractAddress).
- storeCoins(0). // Import fee
- storeBit(1). // We have State Init
- storeBit(1). // We store State Init as a reference
- storeRef(stateInit). // Store State Init as a reference
- storeBit(1). // We store Message Body as a reference
- storeRef(body). // Store Message Body as a reference
- endCell();
+const externalMessage = beginCell()
+ .storeUint(0b10, 2) // indicate that it is an incoming external message
+ .storeUint(0, 2) // src -> addr_none
+ .storeAddress(contractAddress)
+ .storeCoins(0) // Import fee
+ .storeBit(1) // We have State Init
+ .storeBit(1) // We store State Init as a reference
+ .storeRef(stateInit) // Store State Init as a reference
+ .storeBit(1) // We store Message Body as a reference
+ .storeRef(body) // Store Message Body as a reference
+ .endCell();
```
@@ -1129,7 +1129,7 @@ const externalMessage = beginCell().
```go
externalMessage := cell.BeginCell().
- MustStoreUInt(0b10, 2). // indicate that it is an incoming external transaction
+ MustStoreUInt(0b10, 2). // indicate that it is an incoming external message
MustStoreUInt(0, 2). // src -> addr_none
MustStoreAddr(contractAddress).
MustStoreCoins(0). // Import fee
@@ -1144,7 +1144,7 @@ externalMessage := cell.BeginCell().
-Finally, we can send our transaction to the blockchain to deploy our wallet and use it.
+Finally, we can send our message to the blockchain to deploy our wallet and use it.
@@ -1204,7 +1204,7 @@ After completing the first half of this tutorial we’re now much more familiar
### Sending Multiple Messages Simultaneously
-As you may already know, [one cell can store up to 1023 bits of data and up to 4 references](develop/data-formats/cell-boc#cell) to other cells. In the first section of this tutorial we detailed how internal messages are delivered in a ‘whole’ loop as a link and sent. This means it is possible to **store up to 4 internal messages inside the external** message. This allows four transactions to be sent at the same time.
+As you may already know, [one cell can store up to 1023 bits of data and up to 4 references](/develop/data-formats/cell-boc#cell) to other cells. In the first section of this tutorial we detailed how internal messages are delivered in a ‘whole’ loop as a link and sent. This means it is possible to **store up to 4 internal messages inside the external** message. This allows four messages to be sent at the same time.
To accomplish this, it is necessary to create 4 different internal messages. We can do this manually or through a `loop`. We need to define 3 arrays: array of TON amount, array of comments, array of messages. For messages, we need to prepare another one array - internalMessages.
@@ -1218,7 +1218,7 @@ const internalMessagesAmount = ["0.01", "0.02", "0.03", "0.04"];
const internalMessagesComment = [
"Hello, TON! #1",
"Hello, TON! #2",
- "", // Let's leave the third transaction without comment
+ "", // Let's leave the third message without comment
"Hello, TON! #4"
]
const destinationAddresses = [
@@ -1243,7 +1243,7 @@ internalMessagesAmount := [4]string{"0.01", "0.02", "0.03", "0.04"}
internalMessagesComment := [4]string{
"Hello, TON! #1",
"Hello, TON! #2",
- "", // Let's leave the third transaction without comment
+ "", // Let's leave the third message without comment
"Hello, TON! #4",
}
destinationAddresses := [4]string{
@@ -1270,11 +1270,11 @@ import { Address, beginCell, toNano } from '@ton/core';
for (let index = 0; index < internalMessagesAmount.length; index++) {
const amount = internalMessagesAmount[index];
- let internalMessage = beginCell().
- storeUint(0x18, 6). // bounce
- storeAddress(Address.parse(destinationAddresses[index])).
- storeCoins(toNano(amount)).
- storeUint(0, 1 + 4 + 4 + 64 + 32 + 1);
+ let internalMessage = beginCell()
+ .storeUint(0x18, 6) // bounce
+ .storeAddress(Address.parse(destinationAddresses[index]))
+ .storeCoins(toNano(amount))
+ .storeUint(0, 1 + 4 + 4 + 64 + 32 + 1);
/*
At this stage, it is not clear if we will have a message body.
@@ -1286,10 +1286,10 @@ for (let index = 0; index < internalMessagesAmount.length; index++) {
if(internalMessagesComment[index] != "") {
internalMessage.storeBit(1) // we store Message Body as a reference
- let internalMessageBody = beginCell().
- storeUint(0, 32).
- storeStringTail(internalMessagesComment[index]).
- endCell();
+ let internalMessageBody = beginCell()
+ .storeUint(0, 32)
+ .storeStringTail(internalMessagesComment[index])
+ .endCell();
internalMessage.storeRef(internalMessageBody);
}
@@ -1354,7 +1354,7 @@ for i := 0; i < len(internalMessagesAmount); i++ {
-Now let's use our knowledge from [chapter two](/develop/smart-contracts/tutorials/wallet#-deploying-our-wallet) to build a transaction for our wallet that can send 4 transactions simultaneously:
+Now let's use our knowledge from [chapter two](/develop/smart-contracts/tutorials/wallet#-deploying-our-wallet) to build a message for our wallet that can send 4 messages simultaneously:
@@ -1376,11 +1376,11 @@ let seqno = getMethodResult.stack.readNumber(); // get seqno from response
const mnemonicArray = mnemonic.split(' '); // get array from string
const keyPair = await mnemonicToWalletKey(mnemonicArray); // get Secret and Public keys from mnemonic
-let toSign = beginCell().
- storeUint(698983191, 32). // subwallet_id
- storeUint(Math.floor(Date.now() / 1e3) + 60, 32). // Transaction expiration time, +60 = 1 minute
- storeUint(seqno, 32); // store seqno
- // Do not forget that if we use Wallet V4, we need to add storeUint(0, 8).
+let toSign = beginCell()
+ .storeUint(698983191, 32) // subwallet_id
+ .storeUint(Math.floor(Date.now() / 1e3) + 60, 32) // Message expiration time, +60 = 1 minute
+ .storeUint(seqno, 32); // store seqno
+ // Do not forget that if we use Wallet V4, we need to add .storeUint(0, 8)
```
@@ -1437,7 +1437,7 @@ seqno := getMethodResult.MustInt(0) // get seqno from response
toSign := cell.BeginCell().
MustStoreUInt(698983191, 32). // subwallet_id | We consider this further
- MustStoreUInt(uint64(time.Now().UTC().Unix()+60), 32). // transaction expiration time, +60 = 1 minute
+ MustStoreUInt(uint64(time.Now().UTC().Unix()+60), 32). // message expiration time, +60 = 1 minute
MustStoreUInt(seqno.Uint64(), 32) // store seqno
// Do not forget that if we use Wallet V4, we need to add MustStoreUInt(0, 8).
```
@@ -1453,7 +1453,7 @@ Next, we’ll add our messages that we built earlier in the loop:
```js
for (let index = 0; index < internalMessages.length; index++) {
const internalMessage = internalMessages[index];
- toSign.storeUint(3, 8) // store mode of our internal transaction
+ toSign.storeUint(3, 8) // store mode of our internal message
toSign.storeRef(internalMessage) // store our internalMessage as a reference
}
```
@@ -1464,7 +1464,7 @@ for (let index = 0; index < internalMessages.length; index++) {
```go
for i := 0; i < len(internalMessages); i++ {
internalMessage := internalMessages[i]
- toSign.MustStoreUInt(3, 8) // store mode of our internal transaction
+ toSign.MustStoreUInt(3, 8) // store mode of our internal message
toSign.MustStoreRef(internalMessage) // store our internalMessage as a reference
}
```
@@ -1482,20 +1482,20 @@ import { sign } from '@ton/crypto';
let signature = sign(toSign.endCell().hash(), keyPair.secretKey); // get the hash of our message to wallet smart contract and sign it to get signature
-let body = beginCell().
- storeBuffer(signature). // store signature
- storeBuilder(toSign). // store our message
- endCell();
-
-let externalMessage = beginCell().
- storeUint(0b10, 2). // ext_in_msg_info$10
- storeUint(0, 2). // src -> addr_none
- storeAddress(walletAddress). // Destination address
- storeCoins(0). // Import Fee
- storeBit(0). // No State Init
- storeBit(1). // We store Message Body as a reference
- storeRef(body). // Store Message Body as a reference
- endCell();
+let body = beginCell()
+ .storeBuffer(signature) // store signature
+ .storeBuilder(toSign) // store our message
+ .endCell();
+
+let externalMessage = beginCell()
+ .storeUint(0b10, 2) // ext_in_msg_info$10
+ .storeUint(0, 2) // src -> addr_none
+ .storeAddress(walletAddress) // Destination address
+ .storeCoins(0) // Import Fee
+ .storeBit(0) // No State Init
+ .storeBit(1) // We store Message Body as a reference
+ .storeRef(body) // Store Message Body as a reference
+ .endCell();
client.sendFile(externalMessage.toBoc());
```
@@ -1538,20 +1538,20 @@ if err != nil {
:::info Connection error
-If an error related to the lite-server connection (Golang) occurs, the code must be run until the transaction can be sent. This is because the tonutils-go library uses several different lite-servers through the global configuration that have been specified in the code. However, not all lite-servers can accept our connection.
+If an error related to the lite-server connection (Golang) occurs, the code must be run until the message can be sent. This is because the tonutils-go library uses several different lite-servers through the global configuration that have been specified in the code. However, not all lite-servers can accept our connection.
:::
-After this process is completed it is possible to use a TON blockchain explorer to verify that the wallet sent four transactions to the addresses previously specified.
+After this process is completed it is possible to use a TON blockchain explorer to verify that the wallet sent four messages to the addresses previously specified.
### NFT Transfers
-In addition to regular transactions, users often send NFTs to each other. Unfortunately, not all libraries contain methods that are tailored for use with this type of smart contract. Therefore, it is necessary to create code that will allow us to build a transaction for sending NFTs. First, let's become more familiar with the TON NFT [standard](https://github.com/ton-blockchain/TEPs/blob/master/text/0062-nft-standard.md).
+In addition to regular messages, users often send NFTs to each other. Unfortunately, not all libraries contain methods that are tailored for use with this type of smart contract. Therefore, it is necessary to create code that will allow us to build a message for sending NFTs. First, let's become more familiar with the TON NFT [standard](https://github.com/ton-blockchain/TEPs/blob/master/text/0062-nft-standard.md).
Especially, we need to understand TL-B for [NFT Transfers](https://github.com/ton-blockchain/TEPs/blob/master/text/0062-nft-standard.md#1-transfer) in details.
-- `query_id`: Query ID has no value in terms of transaction processing. The NFT contract doesn't validate it; it only reads it. This value can be useful when a service wants to assign a specific query ID to each of its transactions for identification purposes. Therefore, we will set it to 0.
+- `query_id`: Query ID has no value in terms of message processing. The NFT contract doesn't validate it; it only reads it. This value can be useful when a service wants to assign a specific query ID to each of its messages for identification purposes. Therefore, we will set it to 0.
-- `response_destination`: After processing the ownership change transaction there will be extra TON. They will be sent to this address, if specified, otherwise remain on the NFT balance.
+- `response_destination`: After processing the ownership change message there will be extra TON. They will be sent to this address, if specified, otherwise remain on the NFT balance.
- `custom_payload`: The custom_payload is needed to carry out specific tasks and is not used with ordinary NFTs.
@@ -1559,7 +1559,7 @@ Especially, we need to understand TL-B for [NFT Transfers](https://github.com/to
- `forward_payload`: The forward_payload is additional data that can be sent to the new owner together with the forward_amount. For example, using forward_payload allows users to [add a comment during the transfer of the NFT](https://github.com/ton-blockchain/TEPs/blob/master/text/0062-nft-standard.md#forward_payload-format), as shown in the tutorial earlier. However, although the forward_payload is written within TON’s NFT standard, blockchain explorers do not fully support displaying various details. The same problem also exists when displaying Jettons.
-Now let's build the transaction itself:
+Now let's build the message itself:
@@ -1573,21 +1573,21 @@ const nftAddress = Address.parse("put your nft address");
// We can add a comment, but it will not be displayed in the explorers,
// as it is not supported by them at the time of writing the tutorial.
-const forwardPayload = beginCell().
- storeUint(0, 32).
- storeStringTail("Hello, TON!").
- endCell();
-
-const transferNftBody = beginCell().
- storeUint(0x5fcc3d14, 32). // Opcode for NFT transfer
- storeUint(0, 64). // query_id
- storeAddress(destinationAddress). // new_owner
- storeAddress(walletAddress). // response_destination for excesses
- storeBit(0). // we do not have custom_payload
- storeCoins(toNano("0.01")). // forward_amount
- storeBit(1). // we store forward_payload as a reference
- storeRef(forwardPayload). // store forward_payload as a reference
- endCell();
+const forwardPayload = beginCell()
+ .storeUint(0, 32)
+ .storeStringTail("Hello, TON!")
+ .endCell();
+
+const transferNftBody = beginCell()
+ .storeUint(0x5fcc3d14, 32) // Opcode for NFT transfer
+ .storeUint(0, 64) // query_id
+ .storeAddress(destinationAddress) // new_owner
+ .storeAddress(walletAddress) // response_destination for excesses
+ .storeBit(0) // we do not have custom_payload
+ .storeCoins(toNano("0.01")) // forward_amount
+ .storeBit(1) // we store forward_payload as a reference
+ .storeRef(forwardPayload) // store forward_payload as a .reference
+ .endCell();
const internalMessage = beginCell().
storeUint(0x18, 6). // bounce
@@ -1643,7 +1643,7 @@ internalMessage := cell.BeginCell().
The NFT transfer opcode comes from [the same standard](https://github.com/ton-blockchain/TEPs/blob/master/text/0062-nft-standard.md#tl-b-schema).
-Now let's complete the transaction, as is laid out in the previous sections of this tutorial. The correct code needed to complete the transaction is found in the [GitHub repository](/develop/smart-contracts/tutorials/wallet#source-code).
+Now let's complete the message, as is laid out in the previous sections of this tutorial. The correct code needed to complete the message is found in the [GitHub repository](/develop/smart-contracts/tutorials/wallet#source-code).
The same procedure can be completed with Jettons. To conduct this process, read the TL-B [standart](https://github.com/ton-blockchain/TEPs/blob/master/text/0074-jettons-standard.md) for jettons transfer. To this point specifically, a small difference between NFT and Jettons transfers exists.
@@ -1653,10 +1653,9 @@ Smart contracts often make use of [GET methods](/develop/smart-contracts/guideli
Below we’ll learn more about the basics of GET methods used with [V3](https://github.com/ton-blockchain/ton/blob/e37583e5e6e8cd0aebf5142ef7d8db282f10692b/crypto/smartcont/wallet3-code.fc#L31-L41) and [V4](https://github.com/ton-blockchain/wallet-contract/blob/4111fd9e3313ec17d99ca9b5b1656445b5b49d8f/func/wallet-v4-code.fc#L164-L198). Let’s start with the methods that are the same for both wallet versions:
-
Method | Explanation
:---: | :---:
-int seqno() | This method is needed to receive the current seqno and send transactions with the correct value. In previous sections of this tutorial, this method was called often.
+int seqno() | This method is needed to receive the current seqno and send messages with the correct value. In previous sections of this tutorial, this method was called often.
int get_public_key() | This method is used to retrive a public key. The get_public_key() is not broadly used, and can be used by different services. For example, some API services allow for the retrieval of numerous wallets with the same public key
Now let’s move to the methods that only the V4 wallet makes use of:
@@ -1820,7 +1819,7 @@ The response must be `-1`, meaning the result is true. It is also possible to se
### Contract Deployment via Wallet
-In chapter three, we deployed a wallet. To accomplish this, we initially sent some TON and then a transaction from the wallet to deploy a smart contract. However, this process is not broadly used with external transactions and is often primarily used for wallets only. While developing contracts, the deployment process is initialized by sending internal messages.
+In chapter three, we deployed a wallet. To accomplish this, we initially sent some TON and then a message from the wallet to deploy a smart contract. However, this process is not broadly used with external messages and is often primarily used for wallets only. While developing contracts, the deployment process is initialized by sending internal messages.
To accomplish this, will use the V3R2 wallet smart contract that was used in [the third chapter](/develop/smart-contracts/tutorials/wallet#compiling-our-wallet-code).
In this case, we’ll set the `subwallet_id` to `3` or any other number needed to retrieve another address when using the same private key (it's changeable):
@@ -1836,21 +1835,21 @@ const mnemonicArray = 'put your mnemonic'.split(" ");
const keyPair = await mnemonicToWalletKey(mnemonicArray); // extract private and public keys from mnemonic
const codeCell = Cell.fromBase64('te6ccgEBCAEAhgABFP8A9KQT9LzyyAsBAgEgAgMCAUgEBQCW8oMI1xgg0x/TH9MfAvgju/Jj7UTQ0x/TH9P/0VEyuvKhUUS68qIE+QFUEFX5EPKj+ACTINdKltMH1AL7AOgwAaTIyx/LH8v/ye1UAATQMAIBSAYHABe7Oc7UTQ0z8x1wv/gAEbjJftRNDXCx+A==');
-const dataCell = beginCell().
- storeUint(0, 32). // Seqno
- storeUint(3, 32). // Subwallet ID
- storeBuffer(keyPair.publicKey). // Public Key
- endCell();
+const dataCell = beginCell()
+ .storeUint(0, 32) // Seqno
+ .storeUint(3, 32) // Subwallet ID
+ .storeBuffer(keyPair.publicKey) // Public Key
+ .endCell();
-const stateInit = beginCell().
- storeBit(0). // No split_depth
- storeBit(0). // No special
- storeBit(1). // We have code
- storeRef(codeCell).
- storeBit(1). // We have data
- storeRef(dataCell).
- storeBit(0). // No library
- endCell();
+const stateInit = beginCell()
+ .storeBit(0) // No split_depth
+ .storeBit(0) // No special
+ .storeBit(1) // We have code
+ .storeRef(codeCell)
+ .storeBit(1) // We have data
+ .storeRef(dataCell)
+ .storeBit(0) // No library
+ .endCell();
```
@@ -1902,7 +1901,7 @@ stateInit := cell.BeginCell().
-Next we’ll retrieve the address from our contract and build the InternalMessage. Also we add the "Deploying..." comment to our transaction.
+Next we’ll retrieve the address from our contract and build the InternalMessage. Also we add the "Deploying..." comment to our message.
@@ -1913,22 +1912,22 @@ import { Address, toNano } from '@ton/core';
const contractAddress = new Address(0, stateInit.hash()); // get the hash of stateInit to get the address of our smart contract in workchain with ID 0
console.log(`Contract address: ${contractAddress.toString()}`); // Output contract address to console
-const internalMessageBody = beginCell().
- storeUint(0, 32).
- storeStringTail('Deploying...').
- endCell();
+const internalMessageBody = beginCell()
+ .storeUint(0, 32)
+ .storeStringTail('Deploying...')
+ .endCell();
-const internalMessage = beginCell().
- storeUint(0x10, 6). // no bounce
- storeAddress(contractAddress).
- storeCoins(toNano('0.01')).
- storeUint(0, 1 + 4 + 4 + 64 + 32).
- storeBit(1). // We have State Init
- storeBit(1). // We store State Init as a reference
- storeRef(stateInit). // Store State Init as a reference
- storeBit(1). // We store Message Body as a reference
- storeRef(internalMessageBody). // Store Message Body Init as a reference
- endCell();
+const internalMessage = beginCell()
+ .storeUint(0x10, 6) // no bounce
+ .storeAddress(contractAddress)
+ .storeCoins(toNano('0.01'))
+ .storeUint(0, 1 + 4 + 4 + 64 + 32)
+ .storeBit(1) // We have State Init
+ .storeBit(1) // We store State Init as a reference
+ .storeRef(stateInit) // Store State Init as a reference
+ .storeBit(1) // We store Message Body as a reference
+ .storeRef(internalMessageBody) // Store Message Body Init as a reference
+ .endCell();
```
@@ -1989,30 +1988,30 @@ const walletAddress = Address.parse('put your wallet address with which you will
const getMethodResult = await client.runMethod(walletAddress, 'seqno'); // run "seqno" GET method from your wallet contract
const seqno = getMethodResult.stack.readNumber(); // get seqno from response
-// transaction for our wallet
-const toSign = beginCell().
- storeUint(698983191, 32). // subwallet_id
- storeUint(Math.floor(Date.now() / 1e3) + 60, 32). // Transaction expiration time, +60 = 1 minute
- storeUint(seqno, 32). // store seqno
- // Do not forget that if we use Wallet V4, we need to add storeUint(0, 8).
- storeUint(3, 8).
- storeRef(internalMessage);
+// message for our wallet
+const toSign = beginCell()
+ .storeUint(698983191, 32) // subwallet_id
+ .storeUint(Math.floor(Date.now() / 1e3) + 60, 32) // Message expiration time, +60 = 1 minute
+ .storeUint(seqno, 32) // store seqno
+ // Do not forget that if we use Wallet V4, we need to add .storeUint(0, 8)
+ .storeUint(3, 8)
+ .storeRef(internalMessage);
const signature = sign(toSign.endCell().hash(), walletKeyPair.secretKey); // get the hash of our message to wallet smart contract and sign it to get signature
-const body = beginCell().
- storeBuffer(signature). // store signature
- storeBuilder(toSign). // store our message
- endCell();
-
-const external = beginCell().
- storeUint(0b10, 2). // indicate that it is an incoming external transaction
- storeUint(0, 2). // src -> addr_none
- storeAddress(walletAddress).
- storeCoins(0). // Import fee
- storeBit(0). // We do not have State Init
- storeBit(1). // We store Message Body as a reference
- storeRef(body). // Store Message Body as a reference
- endCell();
+const body = beginCell()
+ .storeBuffer(signature) // store signature
+ .storeBuilder(toSign) // store our message
+ .endCell();
+
+const external = beginCell()
+ .storeUint(0b10, 2) // indicate that it is an incoming external message
+ .storeUint(0, 2) // src -> addr_none
+ .storeAddress(walletAddress)
+ .storeCoins(0) // Import fee
+ .storeBit(0) // We do not have State Init
+ .storeBit(1) // We store Message Body as a reference
+ .storeRef(body) // Store Message Body as a reference
+ .endCell();
console.log(external.toBoc().toString('base64'));
client.sendFile(external.toBoc());
@@ -2061,10 +2060,10 @@ seqno := getMethodResult.MustInt(0) // get seqno from response
toSign := cell.BeginCell().
MustStoreUInt(698983191, 32). // subwallet_id | We consider this further
- MustStoreUInt(uint64(time.Now().UTC().Unix()+60), 32). // transaction expiration time, +60 = 1 minute
+ MustStoreUInt(uint64(time.Now().UTC().Unix()+60), 32). // message expiration time, +60 = 1 minute
MustStoreUInt(seqno.Uint64(), 32). // store seqno
// Do not forget that if we use Wallet V4, we need to add MustStoreUInt(0, 8).
- MustStoreUInt(3, 8). // store mode of our internal transaction
+ MustStoreUInt(3, 8). // store mode of our internal message
MustStoreRef(internalMessage) // store our internalMessage as a reference
signature := ed25519.Sign(walletPrivateKey, toSign.EndCell().Hash()) // get the hash of our message to wallet smart contract and sign it to get signature
@@ -2096,13 +2095,432 @@ if err != nil {
-This concludes our work with ordinary wallets. At this stage, you should have a strong understanding of how to interact with wallet smart contracts, send transactions, and be able to use various library types.
+This concludes our work with ordinary wallets. At this stage, you should have a strong understanding of how to interact with wallet smart contracts, send messages, and be able to use various library types.
+
+## 🔥 High-Load Wallet V3
+
+When working with many messages in a short period, there is a need for special wallet called High-Load Wallet. High-Load Wallet V2 was the main wallet on TON for a long time, but you had to be very careful with it. Otherwise, you could [lock all funds](https://t.me/tonstatus/88).
+
+[With the advent of High-Load Wallet V3](https://github.com/ton-blockchain/highload-wallet-contract-v3), this problem has been solved at the contract architecture level and consumes less gas. This chapter will cover the basics of High-Load Wallet V3 and important nuances to remember.
+
+:::note
+We will work [with a slightly modified version of Wrapper](https://github.com/aSpite/highload-wallet-contract-v3/blob/main/wrappers/HighloadWalletV3.ts) for the contract, as it protects against some non-obvious mistakes.
+:::note
+
+
+### Storage Structure
+
+First of all, [TL-B schema](https://github.com/ton-blockchain/highload-wallet-contract-v3/blob/d58c31e82315c34b4db55942851dd8d4153975c5/contracts/scheme.tlb#L1C1-L3C21) will help us in learning the structure of the contract storage:
+
+```
+storage$_ public_key:bits256 subwallet_id:uint32 old_queries:(HashmapE 14 ^Cell)
+ queries:(HashmapE 14 ^Cell) last_clean_time:uint64 timeout:uint22
+ = Storage;
+```
+
+:::tip TL-B
+You can read more about TL-B [here](/develop/data-formats/tl-b-language).
+:::
+
+In the contract storage, we can find the following fields:
+
+| Field | Description |
+| :---: | :---: |
+| public_key | Public key of the contract. |
+| subwallet_id | [Wallet ID](#subwallet-ids). It allows you to create many wallets using the same public key. |
+| old_queries | Old queries that have already been processed and are outdated. They are moved here after each timeout. |
+| queries | Queries that have been processed but are not yet outdated. |
+| last_clean_time | The time of the last cleanup. If `last_clean_time < (now() - timeout)`, old queries are moved to `old_queries`. If `last_clean_time < (now() - 2 * timeout)`, both `old_queries` and `queries` are cleared. |
+| timeout | The time after which queries are moved to `old_queries`. |
+
+We will discuss more about working with processed queries in [Replay Protection](#replay-protection).
+
+### Shifts and Bits Numbers as Query ID
+
+The Query ID is a number that consists of two parts: shift and bit_number:
+
+```func.
+int shift = msg_inner_slice~load_uint(KEY_SIZE);
+int bit_number = msg_inner_slice~load_uint(BIT_NUMBER_SIZE);
+```
+
+The basic idea behind this is that each Query ID now only takes up 1 bit in the dictionary while not increasing gas consumption most of the time.
+
+To start, the contract, using shift, tries to get the cell at that index in the `old_queries` dictionary:
+
+```func
+(cell value, int found) = old_queries.udict_get_ref?(KEY_SIZE, shift);
+```
+
+If such a cell is found, it skips `bit_number` bits to reach the bit with index `bit_number` (it is important to understand the difference between bit_number as a quantity and bit_number as an index). If such a bit is found, it means that a query with such a Query ID has already been processed, and an error is thrown:
+
+```func
+if (found) {
+ slice value_slice = value.begin_parse();
+ value_slice~skip_bits(bit_number);
+ throw_if(error::already_executed, value_slice.preload_int(1));
+}
+```
+
+The next step is to search the `queries` dictionary:
+
+```func
+(cell value, int found) = queries.udict_get_ref?(KEY_SIZE, shift);
+```
+
+If such a cell is found, the contract cuts it into 2 parts: `0...bit_number-1` (head) and `bit_number...1023` (tail). Then, one bit is read from the beginning of the tail (the number of this bit is equal to the `bit_number` variable if you start counting from 0, i.e. it is the index of the required bit). If it is positive, the request with such a Query ID has already been processed, and an error is thrown. Otherwise, the bit is set to 1, and all the pieces are merged into one cell again and written back into the `queries` dictionary:
+
+```func
+builder new_value = null();
+if (found) {
+ slice value_slice = value.begin_parse();
+ (slice tail, slice head) = value_slice.load_bits(bit_number);
+ throw_if(error::already_executed, tail~load_int(1));
+ new_value = begin_cell().store_slice(head).store_true().store_slice(tail);
+} else {
+ new_value = begin_cell().store_zeroes(bit_number).store_true().store_zeroes(CELL_BITS_SIZE - bit_number - 1);
+}
+```
+
+:::note
+If you [familiarize yourself](https://docs.ton.org/learn/tvm-instructions/instructions) with the operation of the `LDSLICEX` opcode (the load_bits function uses this opcode), you will notice that the read data is returned first (head) and only then the remaining data (tail), but they are in reverse order in the contract code.
+
+In fact, they go in reverse order, because in stdlib in the function signature, the returned data [go in reverse order](https://github.com/ton-blockchain/highload-wallet-contract-v3/blob/d58c31e82315c34b4db55942851dd8d4153975c5/contracts/imports/stdlib.fc#L321): `(slice, slice) load_bits(slice s, int len) asm(s len -> 1 0) "LDSLICEX";`. Here `-> 1 0` means to return the argument with index 1 (tail) first, and then 0 (head).
+:::
+
+So in effect we are working with a matrix where `shift` is the row index and `bit_number` is the column index. This allows us to store up to 1023 queries in a single cell, which means that gas consumption will only increase every 1023 queries due to adding a new cell to the dictionary. It is important to realize that this will be done if the values grow sequentially, not randomly, so it is necessary to properly increase Query ID, [using a special class for this](https://github.com/aSpite/highload-wallet-contract-v3/blob/main/wrappers/HighloadQueryId.ts).
+
+This approach allows storing a huge number of requests per timeout (1023 \* 8192 = 8,380,416), but you may notice that [the class HighloadQueryId supports 8,380,415](https://github.com/ton-blockchain/highload-wallet-contract-v3/blob/d58c31e82315c34b4db55942851dd8d4153975c5/wrappers/HighloadQueryId.ts#L32). This is to ensure that there will always be 1 bit left for one emergency timeout request if the entire limit is exhausted. This value is set because of the [limit on the maximum possible number of cells in an account stack](https://github.com/ton-blockchain/ton/blob/5c392e0f2d946877bb79a09ed35068f7b0bd333a/crypto/block/mc-config.h#L395) on the blockchain (as of this writing).
+
+For every cell that can hold 1023 requests, 2 cells in the dictionary are spent (one to store the key, the other for the value). If we take the current maximum shift value, the theoretical maximum is 8192 \* 2 \* 2 (we have two dictionaries: queries and old_queries) = 32,768 cells. If you increase the key size by a bit, it will no longer fit within the current limits.
+
+:::info
+Earlier in High-Load V2, each Query ID (64-bit) was stored in a separate cell in the dictionary and was a union of 32-bit fields `expire_at` and `query_id`. This led to a very fast growth in gas consumption when clearing old queries.
+:::
+
+### Replay Protection
+
+As we know that external messages in TON [have no sender and can be sent by anyone in the network](#replay-protection---seqno), it is important to have a list of processed requests to avoid re-processing. For this purpose, High-Load Wallet V3 uses the `queries` and `old_queries` dictionaries and the `last_clean_time` and `timeout` values.
+
+After the contract has completely retrieved all the data it needs from its storage, it checks to see when the last query dictionary cleanup occurred. If it was more than the `timeout` time ago, the contract moves all queries from queries to old_queries. If the last cleanup was more than `timeout * 2` times ago, the contract cleans up old_queries in addition:
+
+```func
+if (last_clean_time < (now() - timeout)) {
+ (old_queries, queries) = (queries, null());
+ if (last_clean_time < (now() - (timeout * 2))) {
+ old_queries = null();
+ }
+ last_clean_time = now();
+}
+```
+
+The reason for this is that the contract does not keep track of when exactly which request was executed. This means that if `timeout` is 3 hours, but the last request was executed one minute before reaching 3 hours, the request will be considered outdated one minute later, despite the 3-hour timeout. To solve this problem, the second dictionary stores the same queries for at least that much more time.
+
+Theoretically, a query has a lifetime from `timeout` to `timeout * 2`, which means that when tracking which queries are outdated, it is good practice to wait at least `timeout * 2` times to see if the query is obsolete.
+
+### Guaranteed Error-Free Action Phase
+
+Once all the checks and cleanups have been completed, the contract can accept the message, make changes to its storage, and call the commit function, which will consider the compute phase a success even if some error is thrown next:
+
+```func
+accept_message();
+
+queries~udict_set_ref(KEY_SIZE, shift, new_value.end_cell());
+
+set_data(begin_cell()
+ .store_uint(public_key, PUBLIC_KEY_SIZE)
+ .store_uint(subwallet_id, SUBWALLET_ID_SIZE)
+ .store_dict(old_queries)
+ .store_dict(queries)
+ .store_uint(last_clean_time, TIMESTAMP_SIZE)
+ .store_uint(timeout, TIMEOUT_SIZE)
+ .end_cell());
+
+
+commit();
+```
+
+This is done so that when executing further code if there is an error in the message the user is trying to send, the contract does not return to its previous state. Otherwise, the external will remain valid and can be accepted several times, resulting in wasted balance.
+
+However, another issue must be addressed - possible errors during the **Action Phase**. Although we have a flag to ignore the mistakes (2) when sending a message, it doesn't work in all cases, so we need to ensure that no errors occur during this phase, which could cause the state to roll back and make `commit()` meaningless.
+
+For this reason, instead of sending all messages directly, the contract sends itself a message with the `internal_transfer` opcode. This message is parsed in detail by the contract to ensure that no Action Phase error occurs:
+
+```func
+throw_if(error::invalid_message_to_send, message_slice~load_uint(1)); ;; int_msg_info$0
+int msg_flags = message_slice~load_uint(3); ;; ihr_disabled:Bool bounce:Bool bounced:Bool
+if (is_bounced(msg_flags)) {
+ return ();
+}
+slice message_source_adrress = message_slice~load_msg_addr(); ;; src
+throw_unless(error::invalid_message_to_send, is_address_none(message_source_adrress));
+message_slice~load_msg_addr(); ;; dest
+message_slice~load_coins(); ;; value.coins
+message_slice = message_slice.skip_dict(); ;; value.other extra-currencies
+message_slice~load_coins(); ;; ihr_fee
+message_slice~load_coins(); ;; fwd_fee
+message_slice~skip_bits(64 + 32); ;; created_lt:uint64 created_at:uint32
+int maybe_state_init = message_slice~load_uint(1);
+throw_if(error::invalid_message_to_send, maybe_state_init); ;; throw if state-init included (state-init not supported)
+int either_body = message_slice~load_int(1);
+if (either_body) {
+ message_slice~load_ref();
+ message_slice.end_parse();
+}
+```
+
+If any problem occurs while reading the data, it will still be Compute Phase. However, due to the presence of `commit()` this is not a problem and the transaction will still be considered a success. If all data has been read successfully, this is a guarantee that the Action Phase will pass without errors, as these checks cover all cases where the `IGNORE_ERRORS` (2) flag fails. The contract can then complete its work by sending a message:
+
+```func
+;; send message with IGNORE_ERRORS flag to ignore errors in the action phase
+
+send_raw_message(message_to_send, send_mode | SEND_MODE_IGNORE_ERRORS);
+```
+
+### Internal Transfer
+
+After `internal_transfer` reaches the contract, it loads the list of actions, sets them in the c5 register, and then applies `set_code` to protect against accidental code changes, which is also an action. Because of this, the number of messages that can be sent is 254 rather than 255, which is the limit on the blockchain. However, the contract can call itself to send more messages, which we will discuss later:
+
+```func
+if (op == op::internal_transfer) {
+ in_msg_body~skip_query_id();
+ cell actions = in_msg_body.preload_ref();
+ cell old_code = my_code();
+ set_actions(actions);
+ set_code(old_code); ;; prevent to change smart contract code
+ return ();
+}
+```
+
+When dealing with `internal_transfer` there is one important nuance. As we have discussed above, the contract sends a message to itself, but that message is entirely collected on the user side. The problem is that you need to correctly count how much TON will be attached to the message.
+
+In the wrapper in the official repository this field is optional and if the user does not specify it, [mode becomes 128](https://github.com/ton-blockchain/highload-wallet-contract-v3/blob/d58c31e82315c34b4db55942851dd8d4153975c5/wrappers/HighloadWalletV3.ts#L115), which means that the entire balance is sent. The problem is that in such a case there is a **edge case**.
+
+Let's imagine that we want to send out a lot of tokens. After sending out the rest of the TON are returned to our wallet, since we set our address in the `response_destination` field. We start sending out multiple externals at the same time and the following situation occurs:
+
+1. External message A is received, processed and sends the entire contract balance via `internal_transfer`.
+2. Before external message B reaches, part of the commissions from the already completed token sent reaches. Hence, the non-empty contract balance allows the entire balance to be sent to internal message B again, but this time, a very small amount of TONs is sent.
+3. Internal message A is received, processed. Token sending messages are sent.
+4. Before internal message B reaches, external message C manages to reach and sends the entire balance again.
+5. When receiving internal message B, the contract has little TON, even if some extra TON from sending tokens will reach and the request fails with exit code = 37 on Action Phase (Insufficient Funds).
+
+Thus the contract displays that the request has been processed when in fact it has not. To avoid this scenario, it is **recommended to always put 1 TON** on `internal_transfer`. Therefore, [we are working with a modified wrapper](#-high-load-wallet-v3) that requires the user to specify the number of TONs. This value will suffice for all cases, since the external message size is limited to 64 KB and a message close to this limit will spend less than 1 TON.
+
+High-Load Wallet V3 can send more than 254 messages, [putting the remaining messages into the 254th message](https://github.com/aSpite/highload-wallet-contract-v3/blob/d4c1752d00b5303782f121a87eb0620d403d9544/wrappers/HighloadWalletV3.ts#L169-L176). This way `internal_transfer` will be processed several times. The wrapper automatically does this, and we won't have to worry about it, but **recommended to take no more than 150 messages at a time** to ensure that even complex messages will fit into an external message.
+
+:::info
+Although the external message limit is 64KB, the larger the external, the more likely it is to get lost in delivery, so 150 messages is the optimal solution.
+:::
+
+### GET Methods
+
+High-Load Wallet V3 supports the 5 GET methods:
+
+Method | Explanation
+:---: | :---:
+int get_public_key() | Returns the public key of the contract.
+int get_subwallet_id() | Returns the subwallet ID.
+int get_last_clean_time() | Returns the time of the last cleaning.
+int get_timeout() | Returns the timeout value.
+int processed?(int query_id, int need_clean) | Returns whether the query_id has been processed. If need_clean is set to 1, then will first do the cleanup based on `last_clean_time` and `timeout` and then check for query_id in `old_queries` and `queries`.
+
+:::tip
+It is recommended to pass `true` for `need_clean` unless the situation requires otherwise since the most current dictionary states will then be returned.
+:::
+
+Due to how the Query ID is organized in High-Load Wallet V3, we can send a message with the same Query ID again if it does not arrive without fear of the request being processed twice.
+
+However, in such a case, we must consider that no more than `timeout` time has elapsed since the first sending attempt. Otherwise, the request may have been processed but already deleted from the dictionaries. Therefore, it is recommended to set `timeout` to no less than an hour and no more than 24 hours.
+
+
+### Deploying High-Load Wallet V3
+
+To deploy a contract, we need 2 cells: `code` and `date`. For the code, we will use the following cell:
+
+
+
+
+```js
+import { Cell } from "@ton/core";
+
+const HIGHLOAD_V3_CODE = Cell.fromBoc(Buffer.from('b5ee9c7241021001000228000114ff00f4a413f4bcf2c80b01020120020d02014803040078d020d74bc00101c060b0915be101d0d3030171b0915be0fa4030f828c705b39130e0d31f018210ae42e5a4ba9d8040d721d74cf82a01ed55fb04e030020120050a02027306070011adce76a2686b85ffc00201200809001aabb6ed44d0810122d721d70b3f0018aa3bed44d08307d721d70b1f0201200b0c001bb9a6eed44d0810162d721d70b15800e5b8bf2eda2edfb21ab09028409b0ed44d0810120d721f404f404d33fd315d1058e1bf82325a15210b99f326df82305aa0015a112b992306dde923033e2923033e25230800df40f6fa19ed021d721d70a00955f037fdb31e09130e259800df40f6fa19cd001d721d70a00937fdb31e0915be270801f6f2d48308d718d121f900ed44d0d3ffd31ff404f404d33fd315d1f82321a15220b98e12336df82324aa00a112b9926d32de58f82301de541675f910f2a106d0d31fd4d307d30cd309d33fd315d15168baf2a2515abaf2a6f8232aa15250bcf2a304f823bbf2a35304800df40f6fa199d024d721d70a00f2649130e20e01fe5309800df40f6fa18e13d05004d718d20001f264c858cf16cf8301cf168e1030c824cf40cf8384095005a1a514cf40e2f800c94039800df41704c8cbff13cb1ff40012f40012cb3f12cb15c9ed54f80f21d0d30001f265d3020171b0925f03e0fa4001d70b01c000f2a5fa4031fa0031f401fa0031fa00318060d721d300010f0020f265d2000193d431d19130e272b1fb00b585bf03', 'hex'))[0];
+```
+
+
+
+
+Unlike the other examples, here we will work [with a ready-made wrapper](https://github.com/aSpite/highload-wallet-contract-v3/blob/main/wrappers/HighloadWalletV3.ts), as it will be quite difficult and time-consuming to build each message manually. To create an instance of the HighloadWalletV3 class, we pass `publicKey`, `subwalletId` and `timeout` and also the code:
+
+
+
+
+```js
+import { TonClient } from "@ton/ton";
+import { HighloadWalletV3 } from "./wrappers/HighloadWalletV3";
+import { mnemonicToWalletKey } from "@ton/crypto";
+
+const client = new TonClient({
+ endpoint: 'https://toncenter.com/api/v2/jsonRPC',
+ apiKey: 'put your api key' // you can get an api key from @tonapibot bot in Telegram
+});
+
+const walletMnemonicArray = 'put your mnemonic'.split(' ');
+const walletKeyPair = await mnemonicToWalletKey(walletMnemonicArray); // extract private and public keys from mnemonic
+const wallet = client.open(HighloadWalletV3.createFromConfig({
+ publicKey: walletKeyPair.publicKey,
+ subwalletId: 0x10ad,
+ timeout: 60 * 60, // 1 hour
+}, HIGHLOAD_V3_CODE));
+
+console.log(`Wallet address: ${wallet.address.toString()}`);
+```
+
+
+
+
+Now we need a regular wallet, from which we will deploy the contract:
+
+
+
+
+```js
+import { WalletContractV3R2 } from "@ton/ton";
-## 🔥 High-Load Wallets
+const deployerWalletMnemonicArray = 'put your mnemonic'.split(' ');
+const deployerWalletKeyPair = await mnemonicToWalletKey(deployerWalletMnemonicArray); // extract private and public keys from mnemonic
+const deployerWallet = client.open(WalletContractV3R2.create({
+ publicKey: deployerWalletKeyPair.publicKey,
+ workchain: 0
+}));
+console.log(`Deployer wallet address: ${deployerWallet.address.toString()}`);
+```
-In some situations, sending a large number of transactions per message may be necessary. As previously mentioned, ordinary wallets support sending up to 4 transactions at a time by storing [a maximum of 4 references](/develop/data-formats/cell-boc#cell) in a single cell. High-load wallets only allow 255 transactions to be sent at once. This restriction exists because the maximum number of outgoing messages (actions) in the blockchain’s config settings is set to 255.
+
+
-Exchanges are probably the best example of where high-load wallets are used on a large scale. Established exchanges like Binance and others have extremely large user bases, this means that a large number of transaction withdrawals are processed in short time periods. High-load wallets help address these withdrawal requests.
+If you have a V4 version wallet, you can use the `WalletContractV4` class. Now, all we have to do is to deploy the contract:
+
+
+
+
+```js
+await wallet.sendDeploy(deployerWallet.sender(deployerWalletKeyPair.secretKey), toNano(0.05));
+```
+
+
+
+
+By viewing the address that was output to the console in explorer, we can verify that our wallet is deployed.
+
+### Sending High-Load Wallet V3 Messages
+
+Sending messages is also done through the wrapper, but in this case we will need to additionally keep the Query ID up to date. First, let's get an instance of our wallet class:
+
+
+
+
+```js
+import { Address } from "@ton/core";
+import { TonClient } from "@ton/ton";
+import { HighloadWalletV3 } from "./wrappers/HighloadWalletV3";
+import { mnemonicToWalletKey } from "@ton/crypto";
+
+const client = new TonClient({
+ endpoint: 'https://toncenter.com/api/v2/jsonRPC',
+ apiKey: 'put your api key' // you can get an api key from @tonapibot bot in Telegram
+});
+
+const walletMnemonicArray = 'put your mnemonic'.split(' ');
+const walletKeyPair = await mnemonicToWalletKey(walletMnemonicArray); // extract private and public keys from mnemonic
+const wallet = client.open(HighloadWalletV3.createFromAddress(Address.parse('put your high-load wallet address')));
+console.log(`Wallet address: ${wallet.address.toString()}`);
+```
+
+
+
+
+Now we need to create an instance of the `HighloadQueryId` class. This class makes it easy to work with `shift` and `bit_number`. To create it, we use the `fromShiftAndBitNumber` method:
+
+
+
+
+```js
+import { HighloadQueryId } from "./wrappers/HighloadQueryId";
+
+const queryHandler = HighloadQueryId.fromShiftAndBitNumber(0n, 0n);
+```
+
+
+
+
+We put zeros here since this is the first request. However, if you've sent any messages before, you'll need to pick an unused combination of these values. Now let's create an array where we will store all our actions and add one action to it to get our TONs back:
+
+
+
+
+```js
+import { beginCell, internal, OutActionSendMsg, SendMode, toNano } from "@ton/core";
+
+const actions: OutActionSendMsg[] = [];
+actions.push({
+ type: 'sendMsg',
+ mode: SendMode.CARRY_ALL_REMAINING_BALANCE,
+ outMsg: internal({
+ to: Address.parse('put address of deployer wallet'),
+ value: toNano(0),
+ body: beginCell()
+ .storeUint(0, 32)
+ .storeStringTail('Hello, TON!')
+ .endCell()
+ })
+});
+```
+
+
+
+
+Next we just need to fill in the `subwalletId`, `timeout`, `internalMessageValue` and `createdAt` fields to send the message:
+
+
+
+
+```js
+const subwalletId = 0x10ad;
+const timeout = 60 * 60; // must be same as in the contract
+const internalMessageValue = toNano(0.01); // in real case it is recommended to set the value to 1 TON
+const createdAt = Math.floor(Date.now() / 1000) - 60; // LiteServers have some delay in time
+await wallet.sendBatch(
+ walletKeyPair.secretKey,
+ actions,
+ subwalletId,
+ queryHandler,
+ timeout,
+ internalMessageValue,
+ SendMode.PAY_GAS_SEPARATELY,
+ createdAt
+);
+```
+
+
+
+
+After submitting, we should use the `getNext` method in `queryHandler` and save the current value. In a real case, this value should be stored in the database and reset after the `timeout * 2` time.
+
+
+
+
+```js
+queryHandler.getNext();
+```
+
+
+
+
+## 🔥 High-Load Wallet V2 (Outdated)
+
+In some situations, sending a large number of messages per transaction may be necessary. As previously mentioned, ordinary wallets support sending up to 4 messages at a time by storing [a maximum of 4 references](/develop/data-formats/cell-boc#cell) in a single cell. High-load wallets only allow 255 messages to be sent at once. This restriction exists because the maximum number of outgoing messages (actions) in the blockchain’s config settings is set to 255.
+
+Exchanges are probably the best example of where high-load wallets are used on a large scale. Established exchanges like Binance and others have extremely large user bases, this means that a large number of withdrawals messages are processed in short time periods. High-load wallets help address these withdrawal requests.
### High-load wallet FunC code
@@ -2114,7 +2532,7 @@ First, let’s examine [the code structure of high-load wallet smart contract](h
var cs = in_msg;
var (subwallet_id, query_id) = (cs~load_uint(32), cs~load_uint(64)); ;; get rest values from the message body
var bound = (now() << 32); ;; bitwise left shift operation
- throw_if(35, query_id < bound); ;; throw an error if transaction has expired
+ throw_if(35, query_id < bound); ;; throw an error if message has expired
var ds = get_data().begin_parse();
var (stored_subwallet, last_cleaned, public_key, old_queries) = (ds~load_uint(32), ds~load_uint(64), ds~load_uint(256), ds~load_dict()); ;; read values from storage
ds.end_parse(); ;; make sure we do not have anything in ds
@@ -2139,10 +2557,10 @@ You notice some differences from ordinary wallets. Now let’s take a closer loo
### Using a Query ID In Place Of a Seqno
-As we previously discussed, ordinary wallet seqno increase by `1` after each transaction. While using a wallet sequence we had to wait until this value was updated, then retrieve it using the GET method and send a new transaction.
-This process takes a significant amount of time which high-load wallets are not designed for (as discussed above, they are meant to send a large number of transactions very quickly). Therefore, high-load wallets on TON make use of the `query_id`.
+As we previously discussed, ordinary wallet seqno increase by `1` after each transaction. While using a wallet sequence we had to wait until this value was updated, then retrieve it using the GET method and send a new message.
+This process takes a significant amount of time which high-load wallets are not designed for (as discussed above, they are meant to send a large number of messages very quickly). Therefore, high-load wallets on TON make use of the `query_id`.
-If the same transaction request already exists, the contract won’t accept it, as it has already been processed:
+If the same message request already exists, the contract won’t accept it, as it has already been processed:
```func
var (stored_subwallet, last_cleaned, public_key, old_queries) = (ds~load_uint(32), ds~load_uint(64), ds~load_uint(256), ds~load_dict()); ;; read values from storage
@@ -2151,19 +2569,19 @@ ds.end_parse(); ;; make sure we do not have anything in ds
throw_if(32, found?); ;; if yes throw an error
```
-This way, we are **being protected from repeat transactions**, which was the role of seqno in ordinary wallets.
+This way, we are **being protected from repeat messages**, which was the role of seqno in ordinary wallets.
-### Sending Transactions
+### Sending Messages
-After the contract has accepted the external message, a loop starts, in which the `slices` stored in the dictionary are taken. These slices store transaction modes and the transactions themselves. Sending new transactions takes place until the dictionary is empty.
+After the contract has accepted the external message, a loop starts, in which the `slices` stored in the dictionary are taken. These slices store messages' modes and the messages themselves. Sending new messages takes place until the dictionary is empty.
```func
int i = -1; ;; we write -1 because it will be the smallest value among all dictionary keys
do {
(i, var cs, var f) = dict.idict_get_next?(16, i); ;; get the key and its corresponding value with the smallest key, which is greater than i
if (f) { ;; check if any value was found
- var mode = cs~load_uint(8); ;; load transaction mode
- send_raw_message(cs~load_ref(), mode); ;; load transaction itself and send it
+ var mode = cs~load_uint(8); ;; load message mode
+ send_raw_message(cs~load_ref(), mode); ;; load message itself and send it
}
} until (~ f); ;; if any value was found continue
```
@@ -2172,11 +2590,12 @@ do {
>
> ["idict_get_next()" in docs](/develop/func/stdlib/#dict_get_next)
-Note that if a value is found, `f` is always equal to -1 (true). The `~ -1` operation (bitwise not) will always return a value of 0, meaning that the loop should be continued. At the same time, when a dictionary is filled with transactions, it is necessary to start calculating those **with a value greater than -1** (e.g., 0) and continue increasing the value by 1 with each transaction. This structure allows transactions to be sent in the correct sequential order.
+Note that if a value is found, `f` is always equal to -1 (true). The `~ -1` operation (bitwise not) will always return a value of 0, meaning that the loop should be continued. At the same time, when a dictionary is filled with messages, it is necessary to start calculating those **with a value greater than -1** (e.g., 0) and continue increasing the value by 1 with each message. This structure allows messages to be sent in the correct sequential order.
### Removing Expired Queries
-Typically, [smart contracts on TON pay for their own storage](develop/smart-contracts/fees#storage-fee). This means that the amount of data smart contracts can store is limited to prevent high network transaction fees. To allow the system to be more efficient, transactions that are more than 64 seconds old are removed from the storage. This is conducted as follows:
+Typically, [smart contracts on TON pay for their own storage](/develop/howto/fees-low-level#storage-fee). This means that the amount of data smart contracts can store is limited to prevent high network loading. To allow the system to be more efficient, messages that are more than 64 seconds old are removed from the storage. This is conducted as follows:
+
```func
bound -= (64 << 32); ;; clean up records that have expired more than 64 seconds ago
@@ -2199,7 +2618,7 @@ do {
>
> ["udict_delete_get_min()" in docs](/develop/func/stdlib/#dict_delete_get_min)
-Note that it is necessary to interact with the `f` variable several times. Since the [TVM is a stack machine](learn/tvm-instructions/tvm-overview#tvm-is-a-stack-machine), during each interaction with the `f` variable it is necessary to pop all values to get the desired variable. The `f~touch()` operation places the f variable at the top of the stack to optimize code execution.
+Note that it is necessary to interact with the `f` variable several times. Since the [TVM is a stack machine](/learn/tvm-instructions/tvm-overview#tvm-is-a-stack-machine), during each interaction with the `f` variable it is necessary to pop all values to get the desired variable. The `f~touch()` operation places the f variable at the top of the stack to optimize code execution.
### Bitwise Operations
@@ -2245,7 +2664,7 @@ After all operations are complete, the only task remaining is to save the new va
### GET Methods
-The last thing we have to consider before we dive into wallet deployment and transaction creation is high-load wallet GET methods:
+The last thing we have to consider before we dive into wallet deployment and message creation is high-load wallet GET methods:
Method | Explanation
:---: | :---:
@@ -2267,7 +2686,7 @@ The `last_cleaned` is retrieved from the storage of the contract and a dictionar
This means that if the query_id passed to the method is smaller than the last last_cleaned value, it is impossible to determine whether it was ever in the contract or not. Therefore the `query_id <= last_cleaned` returns -1 while the minus before this expression changes the answer to 1. If query_id is larger than last_cleaned method, then it has not yet been processed.
-### Deploying High-Load Wallets
+### Deploying High-Load Wallet V2
In order to deploy a high-load wallet it is necessary to generate a mnemonic key in advance, which will be used by the user. It is possible to use the same key that was used in previous sections of this tutorial.
@@ -2350,22 +2769,22 @@ import { mnemonicToWalletKey } from '@ton/crypto';
const highloadMnemonicArray = 'put your mnemonic that you have generated and saved before'.split(' ');
const highloadKeyPair = await mnemonicToWalletKey(highloadMnemonicArray); // extract private and public keys from mnemonic
-const dataCell = beginCell().
- storeUint(698983191, 32). // Subwallet ID
- storeUint(0, 64). // Last cleaned
- storeBuffer(highloadKeyPair.publicKey). // Public Key
- storeBit(0). // indicate that the dictionary is empty
- endCell();
-
-const stateInit = beginCell().
- storeBit(0). // No split_depth
- storeBit(0). // No special
- storeBit(1). // We have code
- storeRef(codeCell).
- storeBit(1). // We have data
- storeRef(dataCell).
- storeBit(0). // No library
- endCell();
+const dataCell = beginCell()
+ .storeUint(698983191, 32) // Subwallet ID
+ .storeUint(0, 64) // Last cleaned
+ .storeBuffer(highloadKeyPair.publicKey) // Public Key
+ .storeBit(0) // indicate that the dictionary is empty
+ .endCell();
+
+const stateInit = beginCell()
+ .storeBit(0) // No split_depth
+ .storeBit(0) // No special
+ .storeBit(1) // We have code
+ .storeRef(codeCell)
+ .storeBit(1) // We have data
+ .storeRef(dataCell)
+ .storeBit(0) // No library
+ .endCell();
const contractAddress = new Address(0, stateInit.hash()); // get the hash of stateInit to get the address of our smart contract in workchain with ID 0
console.log(`Contract address: ${contractAddress.toString()}`); // Output contract address to console
@@ -2416,11 +2835,13 @@ log.Println("Contract address:", contractAddress.String()) // Output contract
-Everything we have detailed above follows the same steps as the contract [deployment via wallet](/develop/smart-contracts/tutorials/wallet#contract-deployment-via-wallet) section. To better analyze the fully functional code, please visit the repository indicated at the beginning of the tutorial where all sources are stored.
+:::caution
+Everything we have detailed above follows the same steps as the contract [deployment via wallet](/develop/smart-contracts/tutorials/wallet#contract-deployment-via-wallet) section. To better understanding, read the entire [GitHub source code]((https://github.com/aSpite/wallet-tutorial)).
+:::
-### Sending High-Load Wallet Transactions
+### Sending High-Load Wallet V2 Messages
-Now let’s program a high-load wallet to send several messages at the same time. For example, let's take 12 transactions per message so that the gas fees are small.
+Now let’s program a high-load wallet to send several messages at the same time. For example, let's take 12 messages per transaction so that the gas fees are small.
:::info High-load balance
To complete the transaction, the balance of the contract must be at least 0.5 TON.
@@ -2438,20 +2859,20 @@ let internalMessages:Cell[] = [];
const walletAddress = Address.parse('put your wallet address from which you deployed high-load wallet');
for (let i = 0; i < 12; i++) {
- const internalMessageBody = beginCell().
- storeUint(0, 32).
- storeStringTail(`Hello, TON! #${i}`).
- endCell();
-
- const internalMessage = beginCell().
- storeUint(0x18, 6). // bounce
- storeAddress(walletAddress).
- storeCoins(toNano('0.01')).
- storeUint(0, 1 + 4 + 4 + 64 + 32).
- storeBit(0). // We do not have State Init
- storeBit(1). // We store Message Body as a reference
- storeRef(internalMessageBody). // Store Message Body Init as a reference
- endCell();
+ const internalMessageBody = beginCell()
+ .storeUint(0, 32)
+ .storeStringTail(`Hello, TON! #${i}`)
+ .endCell();
+
+ const internalMessage = beginCell()
+ .storeUint(0x18, 6) // bounce
+ .storeAddress(walletAddress)
+ .storeCoins(toNano('0.01'))
+ .storeUint(0, 1 + 4 + 4 + 64 + 32)
+ .storeBit(0) // We do not have State Init
+ .storeBit(1) // We store Message Body as a reference
+ .storeRef(internalMessageBody) // Store Message Body Init as a reference
+ .endCell();
internalMessages.push(internalMessage);
}
@@ -2469,7 +2890,7 @@ import (
)
var internalMessages []*cell.Cell
-wallletAddress := address.MustParseAddr("put your wallet address from which you deployed high-load wallet")
+walletAddress := address.MustParseAddr("put your wallet address from which you deployed high-load wallet")
for i := 0; i < 12; i++ {
comment := fmt.Sprintf("Hello, TON! #%d", i)
@@ -2480,7 +2901,7 @@ for i := 0; i < 12; i++ {
internalMessage := cell.BeginCell().
MustStoreUInt(0x18, 6). // bounce
- MustStoreAddr(wallletAddress).
+ MustStoreAddr(walletAddress).
MustStoreBigCoins(tlb.MustFromTON("0.001").NanoTON()).
MustStoreUInt(0, 1+4+4+64+32).
MustStoreBoolBit(false). // We do not have State Init
@@ -2522,23 +2943,23 @@ const timeout = 120; // timeout for message expiration, 120 seconds = 2 minutes
const finalQueryID = (BigInt(now + timeout) << 32n) + BigInt(queryID); // get our final query_id
console.log(finalQueryID); // print query_id. With this query_id we can call GET method to check if our request has been processed
-const toSign = beginCell().
- storeUint(698983191, 32). // subwallet_id
- storeUint(finalQueryID, 64).
+const toSign = beginCell()
+ .storeUint(698983191, 32) // subwallet_id
+ .storeUint(finalQueryID, 64)
// Here we create our own method that will save the
- // transaction mode and a reference to the transaction
- storeDict(dictionary, Dictionary.Keys.Int(16), {
+ // message mode and a reference to the message
+ .storeDict(dictionary, Dictionary.Keys.Int(16), {
serialize: (src, buidler) => {
- buidler.storeUint(3, 8); // save transaction mode, mode = 3
- buidler.storeRef(src); // save transaction as reference
+ buidler.storeUint(3, 8); // save message mode, mode = 3
+ buidler.storeRef(src); // save message as reference
},
// We won't actually use this, but this method
// will help to read our dictionary that we saved
parse: (src) => {
- let cell = beginCell().
- storeUint(src.loadUint(8), 8).
- storeRef(src.loadRef()).
- endCell();
+ let cell = beginCell()
+ .storeUint(src.loadUint(8), 8)
+ .storeRef(src.loadRef())
+ .endCell();
return cell;
}
}
@@ -2602,7 +3023,7 @@ signature := ed25519.Sign(highloadPrivateKey, toSign.EndCell().Hash())
:::note IMPORTANT
-Note that while using JavaScript and TypeScript that our messages were saved into an array without using a send mode. This occurs because during using @ton/ton library, it is expected that developer will implement process of serialization and deserialization by own hands. Therefore, a method is passed that first saves the transaction mode after it saves the transaction itself. If we make use of the `Dictionary.Values.Cell()` specification for the value method, it saves the entire message as a cell reference without saving the mode separately.
+Note that while using JavaScript and TypeScript that our messages were saved into an array without using a send mode. This occurs because during using @ton/ton library, it is expected that developer will implement process of serialization and deserialization by own hands. Therefore, a method is passed that first saves the message mode after it saves the message itself. If we make use of the `Dictionary.Values.Cell()` specification for the value method, it saves the entire message as a cell reference without saving the mode separately.
:::
Next we’ll create an external message and send it to the blockchain using the following code:
@@ -2613,20 +3034,20 @@ Next we’ll create an external message and send it to the blockchain using the
```js
import { TonClient } from '@ton/ton';
-const body = beginCell().
- storeBuffer(signature). // store signature
- storeBuilder(toSign). // store our message
- endCell();
-
-const externalMessage = beginCell().
- storeUint(0b10, 2). // indicate that it is an incoming external transaction
- storeUint(0, 2). // src -> addr_none
- storeAddress(highloadWalletAddress).
- storeCoins(0). // Import fee
- storeBit(0). // We do not have State Init
- storeBit(1). // We store Message Body as a reference
- storeRef(body). // Store Message Body as a reference
- endCell();
+const body = beginCell()
+ .storeBuffer(signature) // store signature
+ .storeBuilder(toSign) // store our message
+ .endCell();
+
+const externalMessage = beginCell()
+ .storeUint(0b10, 2) // indicate that it is an incoming external message
+ .storeUint(0, 2) // src -> addr_none
+ .storeAddress(highloadWalletAddress)
+ .storeCoins(0) // Import fee
+ .storeBit(0) // We do not have State Init
+ .storeBit(1) // We store Message Body as a reference
+ .storeRef(body) // Store Message Body as a reference
+ .endCell();
// We do not need a key here as we will be sending 1 request per second
const client = new TonClient({
@@ -2683,7 +3104,7 @@ if err != nil {
-After this process is completed it is possible to look up our wallet and verify that 12 outgoing transactions were sent on our wallet. Is it also possible to call the `processed?` GET method using the query_id we initially used in the console. If this request has been processed correctly it provides a result of `-1` (true).
+After this process is completed it is possible to look up our wallet and verify that 12 outgoing messages were sent on our wallet. Is it also possible to call the `processed?` GET method using the query_id we initially used in the console. If this request has been processed correctly it provides a result of `-1` (true).
## 🏁 Conclusion
@@ -2693,9 +3114,9 @@ This helps us to be independent of using libraries and to understand the structu
## 🧩 Next Steps
-Reading the documentation provided above is a complex undertaking and it’s difficult to understand the entirety of the TON platform. However, it is a good exercise for those passionate about building on the TON. Another suggestion is to begin learning about how how to write smart contracts on TON by consulting the following resources: [FunC Overview](https://docs.ton.org/develop/func/overview), [Best Practices](https://docs.ton.org/develop/smart-contracts/guidelines), [Examples of Smart Contracts](https://docs.ton.org/develop/smart-contracts/examples), [FunC Cookbook](https://docs.ton.org/develop/func/cookbook)
+Reading the documentation provided above is a complex undertaking and it’s difficult to understand the entirety of the TON platform. However, it is a good exercise for those passionate about building on the TON. Another suggestion is to begin learning about how to write smart contracts on TON by consulting the following resources: [FunC Overview](https://docs.ton.org/develop/func/overview), [Best Practices](https://docs.ton.org/develop/smart-contracts/guidelines), [Examples of Smart Contracts](https://docs.ton.org/develop/smart-contracts/examples), [FunC Cookbook](https://docs.ton.org/develop/func/cookbook)
-Additionally, it is recommended that readers familiarize themselves with the following documents in more detail: [ton.pdf](https://ton.org/ton.pdf) and [tblkch.pdf](https://ton.org/tblkch.pdf) documents.
+Additionally, it is recommended that readers familiarize themselves with the following documents in more detail: [ton.pdf](https://docs.ton.org/ton.pdf) and [tblkch.pdf](https://ton.org/tblkch.pdf) documents.
## 📬 About the Author
@@ -2705,7 +3126,7 @@ If you have any questions, comments, or suggestions please reach out to the auth
- Wallets' source code: [V3](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/wallet3-code.fc), [V4](https://github.com/ton-blockchain/wallet-contract/blob/main/func/wallet-v4-code.fc), [High-load](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/highload-wallet-v2-code.fc)
-- Useful official documents: [ton.pdf](https://ton.org/ton.pdf), [tblkch.pdf](https://ton.org/tblkch.pdf), [tvm.pdf](https://ton.org/tvm.pdf)
+- Useful concept documents(may include outdated information): [ton.pdf](https://docs.ton.org/ton.pdf), [tblkch.pdf](https://ton.org/tblkch.pdf), [tvm.pdf](https://ton.org/tvm.pdf)
The main sources of code:
diff --git a/docs/learn/academy/academy-overview.md b/docs/learn/academy/academy-overview.md
new file mode 100644
index 0000000000..2ffe955aae
--- /dev/null
+++ b/docs/learn/academy/academy-overview.md
@@ -0,0 +1,75 @@
+import Button from '@site/src/components/button'
+
+# Educational Resources
+
+### TON Speedrun
+
+* [TON Speedrun](https://tonspeedrun.com/) - A specialized platform designed for a practical approach to learning in TON development.
+
+### Courses
+
+#### Blockchain Basics with TON
+
+This course introduces blockchain basics, with a special focus on practical skills in the TON ecosystem. You will understand how blockchain functions and its diverse applications.
+
+````mdx-code-block
+
+````
+Check Blockchain Basics Course
+````mdx-code-block
+
+````
+````mdx-code-block
+
+````
+CHN
+````mdx-code-block
+
+````
+````mdx-code-block
+
+````
+RU
+````mdx-code-block
+
+````
+
+#### TON & Telegram Blockchain Сourse
+
+We're proud to present the __TON Blockchain Course__, which is a comprehensive guide to the TON Blockchain. The course is designed for developers who want to learn how to create smart contracts and decentralized applications on the TON Blockchain in engaging and interactive ways.
+
+It consists of __9 modules__ and covers the basics of the TON Blockchain, the FunC programming language, and the TON Virtual Machine (TVM).
+
+````mdx-code-block
+
+````
+Check TON Blockchain Course
+````mdx-code-block
+
+````
+````mdx-code-block
+
+````
+CHN
+````mdx-code-block
+
+````
+````mdx-code-block
+
+````
+RU
+````mdx-code-block
+
+````
+
+## See Also
+
+* [Speedrun TON](https://tonspeedrun.com/)
+* [TON Hello World](https://tonhelloworld.com/01-wallet/)
+* [[YouTube] TON Dev Study EN ](https://www.youtube.com/@TONDevStudy)[[RU]](https://www.youtube.com/results?search_query=tondevstudy)
\ No newline at end of file
diff --git a/docs/learn/docs.md b/docs/learn/docs.md
index 97fe79c23b..2211ee2268 100644
--- a/docs/learn/docs.md
+++ b/docs/learn/docs.md
@@ -14,7 +14,7 @@ Please note that here and later the code, comments and/or documentation may cont
* [TON Virtual Machine](https://docs.ton.org/tvm.pdf)
- TON Virtual Machine description.
+ TON Virtual Machine description(may include outdated information on OP Codes, actual list in [TVM Instruction](https://docs.ton.org/learn/tvm-instructions/tvm-overview) section).
* [TON Blockchain](https://docs.ton.org/tblkch.pdf)
@@ -31,4 +31,5 @@ Please note that here and later the code, comments and/or documentation may cont
## Translations
* **\[RU]** [korolyow/ton_docs_ru](https://github.com/Korolyow/TON_docs_ru) — TON Whitepapers in Russian. (_this version made by community, TON Foundation can't guarantee quality of translation_)
-* **\[CN]** [awesome-doge/the-open-network-whitepaper](https://github.com/awesome-doge/TON_Paper/blob/main/zh_ton.pdf) — TON Whitepapers in Chinese. (_made by community, TON Foundation can't guarantee quality of translation_)
+* **\[Traditional CN]** [awesome-doge/the-open-network-whitepaper](https://github.com/awesome-doge/TON_Paper/blob/main/zh_ton.pdf) — TON Whitepapers in Traditional Chinese. (_made by community, TON Foundation can't guarantee quality of translation_)
+* **\[Simplified CN]** [kojhliang/Ton_White_Paper_SC](https://github.com/kojhliang/Ton_White_Paper_SC/blob/main/Ton%E5%8C%BA%E5%9D%97%E9%93%BE%E7%99%BD%E7%9A%AE%E4%B9%A6_%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87%E7%89%88.pdf) — TON Whitepapers in Simplified Chinese. (_made by community, TON Foundation can't guarantee quality of translation_)
diff --git a/docs/learn/glossary.md b/docs/learn/glossary.md
index ab97215926..f74be990bb 100644
--- a/docs/learn/glossary.md
+++ b/docs/learn/glossary.md
@@ -66,7 +66,7 @@ ____________
### Bridge
-**Bridge** — a program connecting various blockchains to transfer tokens and data from one network to another. TON Bridge is available by this [link](https://ton.org/bridge/).
+**Bridge** — a program connecting various blockchains to transfer tokens and data from one network to another. TON Bridge is available at this [link](https://ton.org/bridge/).
### Bullish
@@ -204,7 +204,7 @@ ___________
**Gas** — the fee paid for transactions on the blockchain.
-### Github
+### GitHub
**GitHub** — a platform where developers gather to create base code for programs.
@@ -445,6 +445,10 @@ ________
**TVL** (Total Value Locked) — Тotal value locked represents the number of assets currently being staked in a specific protocol.
+### TVM
+
+**TVM** — Ton Virtual Machine, a machine behaving like a decentralized computer, it computes the state of the Ton blockchain after each new block and executes smart contracts.
+
___________
## V
diff --git a/docs/learn/introduction.mdx b/docs/learn/introduction.mdx
index 2275846013..6b2f06cace 100644
--- a/docs/learn/introduction.mdx
+++ b/docs/learn/introduction.mdx
@@ -1,4 +1,6 @@
import Player from '@site/src/components/player'
+import Button from '@site/src/components/button'
+
# The Open Network
@@ -19,6 +21,44 @@ To understand the true vision for the decentralized internet and how TON contrib
+## Blockchain Basics with TON
+
+This course introduces blockchain basics, with a special focus on practical skills in the TON ecosystem. You will understand how blockchain functions and its diverse applications. You will also acquire crucial TON-related skills, including wallet setup, NFT trading, Jetton creation, and transactions with TON coins on decentralized exchanges (DEX). The course will also equip you with critical knowledge about cryptocurrency threats and fraud and give practical tips on how to protect your crypto assets.
+
+- [Blockchain Basics with TON](https://stepik.org/course/201294/) ([RU version](https://stepik.org/course/202221/), [CHN version](https://stepik.org/course/200976/))
+
+## TON Blockchain Course
+
+We're proud to present the __TON Blockchain Course__, which is a comprehensive guide to the TON Blockchain. The course is designed for developers who want to learn how to create smart contracts and decentralized applications on the TON Blockchain.
+
+It consists of __9 modules__ and covers the basics of the TON Blockchain, the FunC programming language, and the TON Virtual Machine (TVM).
+
+````mdx-code-block
+
+````
+Check TON Course
+````mdx-code-block
+
+````
+````mdx-code-block
+
+````
+CHN
+````mdx-code-block
+
+````
+````mdx-code-block
+
+````
+RU
+````mdx-code-block
+
+````
+
+
## New to Blockchain?
If you're new to blockchain and don’t understand what makes the technology so revolutionary — consider taking a deep dive into these important resources:
diff --git a/docs/learn/overviews/addresses.md b/docs/learn/overviews/addresses.md
index 73c286fdd9..d5b89d9e89 100644
--- a/docs/learn/overviews/addresses.md
+++ b/docs/learn/overviews/addresses.md
@@ -1,12 +1,12 @@
# Smart Contract Addresses
-This section will detail the specifics of smart contract addresses on TON Blockchain. It will also explain how actors are synonymous with smart contracts on TON.
+This section will describe the specifics of smart contract addresses on TON Blockchain. It will also explain how actors are synonymous with smart contracts on TON.
## Everything is a Smart Contract
-On TON, smart contracts are built using the [Actor model](/learn/overviews/ton-blockchain#single-actor). In fact, actors in TON are technically represented as smart contracts. This means that even your wallet is a simple actor (and smart contract).
+On TON, smart contracts are built using the [Actor model](/learn/overviews/ton-blockchain#single-actor). In fact, actors in TON are technically represented as smart contracts. This means that even your wallet is a simple actor (and a smart contract).
-Typically, actors process incoming messages, change their internal state, and generate outbound messages as a result. That's why every actor (i.e., smart contract) on TON Blockchain must have an address so it is able to receive messages from other actors.
+Typically, actors process incoming messages, change their internal state, and generate outbound messages as a result. That's why every actor (i.e., smart contract) on TON Blockchain must have an address, so it is able to receive messages from other actors.
:::info EVM EXPERIENCE
On the Ethereum Virtual Machine (EVM), addresses are completely separate from smart contracts. Feel free to learn more about the differences by reading our article ["Six unique aspects of TON Blockchain that will surprise Solidity developers"](https://blog.ton.org/six-unique-aspects-of-ton-blockchain-that-will-surprise-solidity-developers) by Tal Kol.
@@ -30,27 +30,36 @@ In the raw address overview section of this documentation, we'll discuss how **
Nowadays, only the Masterchain (workchain_id=-1) and occasionally the basic workchain (workchain_id=0) are running in TON Blockchain.
-Both of them have 256-bit addresses, so we henceforth assume that workchain_id is either 0 or -1 and that the address inside the workchain is exactly 256-bit.
+Both of them have 256-bit addresses, therefore, we assume that the workchain_id is either 0 or -1, and the address within the workchain is precisely 256 bits.
#### Account ID
-All account IDs on TON make use of 256-bit addresses on the MasterChain and BaseChain (or basic workchain).
+All account IDs on TON make use of 256-bit addresses on the Masterchain and Basechain (or basic workchain).
-In fact, Account ID’s **(account_id)** defined as hash functions for smart contract objects (particular, the SHA256). Every smart contract operating on TON Blockchain stores two main components. These include:
+In fact, Account ID’s **(account_id)** defined as hash functions for smart contract objects (particular, the SHA-256). Every smart contract operating on TON Blockchain stores two main components. These include:
-1. _Compiled code_. Logic of smart contract compiled in byte code.
-2. _Initial state_. Contract’s values in its initial moment deploying on-chain.
+1. _Compiled code_. Logic of the smart contract compiled in the form of bytecode.
+2. _Initial state_. The contract's values at the moment of its deployment on-chain.
-Finally, to correctly receive the address account it is necessary to calculate the hash corresponding to the pair **(Initial code, Initial state)** object. At this time, we won't take a deep dive into how the [TVM](/learn/tvm-instructions/tvm-overview) works, but it's important to understand that account ID’s on TON are determined using this formula:
+Finally, to accurately derive the contract's address, it is necessary to calculate the hash corresponding to the pair **(Initial code, Initial state)** object. At this time, we won't take a deep dive into how the [TVM](/learn/tvm-instructions/tvm-overview) works, but it's important to understand that account IDs on TON are determined using this formula:
:
**account_id = hash(initial code, initial state)**
-In time, throughout this documentation, we'll dive deeper into the technical specifications and overview of the TVM and TL-B scheme. Now that we are familiar with the formation of **account_id** and their interaction with smart contract addresses on TON, let’s explain Raw and User-Friendly addresses.
+In time, throughout this documentation, we'll dive deeper into the technical specifications and overview of the TVM and TL-B scheme. Now that we are familiar with the generation of the **account_id** and their interaction with smart contract addresses on TON, let’s explain Raw and User-Friendly addresses.
+
+## Addresses state
+
+Each address can be in one of possible states:
+
+- `nonexist` - there were no accepted transactions on this address, so it doesn't have any data (or the contract was deleted). We can say that initially all 2256 address are in this state.
+- `uninit` - address has some data, which contains balance and meta info. At this state address doesn't have any smart contract code/persistent data yet. An address enters this state, for example, when it was nonexist and some other address sent some tokens to it.
+- `active` - address has smart contract code, persistent data and balance. At this state it can perform some logic during the transaction and change its persistent data. An address enters this state when it was `uninit` and there was an incoming message with state_init param (note, that to be able to deploy this address, hash of `state_init` and `code` must be equal to address).
+- `frozen` - address cannot perform any operations, this state contains only two hashes of the previous state (code and state cells respectively). When an address's storage charge exceeds its balance, it goes into this state. To unfreeze it, you can send an internal message with `state_init` and `code` which store the hashes described earlier and some Toncoin. It can be difficult to recover it, so you should not allow this situation. There is a project to unfreeze the address, which you can find [here](https://unfreezer.ton.org/).
## Raw and User-Friendly Addresses
-After providing a brief overview of how smart contract addresses on TON leverage workchains and account ID’s (for the MasterChain and BaseChain specifically), it's important to understand that these addresses are expressed in two main formats:
+After providing a brief overview of how smart contract addresses on TON leverage workchains and account IDs (for the Masterchain and Basechain specifically), it is important to understand that these addresses are expressed in two main formats:
* **Raw addresses**: Original full representation of smart contract addresses.
* **User-friendly addresses**: User-friendly addresses are an enhanced format of raw address that employ better security and ease of use.
@@ -68,7 +77,7 @@ Provided below, is an example of a raw smart contract address using a workchain
`-1:fcb91a3a3816d0f7b8c2c76108b8a9bc5a6b7a55bd79f8ab101c52db29232260`
-Notice the `-1` at the start of the address string, this denotes a _workchain_id_ that belongs to the MasterChain.
+Notice the `-1` at the start of the address string, which denotes a _workchain_id_ that belongs to the Masterchain.
:::note
Uppercase letters (such as 'A', ‘B’, ‘C’, ‘D’ etc.) may be used in address strings instead of their lower-case counterparts (such as 'a', ‘b’, ’c’ 'd' etc.).
@@ -85,7 +94,7 @@ Using the Raw Address form presents two main issues:
### User-Friendly Address
-User-friendly addresses were developed to secure and simplify the experience for TON users who share addresses on the internet (for example, on public messaging platforms and via their email service providers) and in the real world.
+User-friendly addresses were developed to secure and simplify the experience for TON users who share addresses on the internet (for example, on public messaging platforms or via their email service providers), as well as in the real world.
#### User-Friendly Address Structure
@@ -96,12 +105,12 @@ User-friendly addresses are made up of 36 bytes in total and are obtained by gen
- isBounceable. Denotes a bounceable or non-bounceable address type. (_0x11_ for "bounceable", _0x51_ for "non-bounceable")
- isTestnetOnly. Denotes an address type used for testnet purposes only. Addresses beginning with _0x80_ should not be accepted by software running on the production network
- - isUrlSafe. Denotes a deprecated flag that is defined as url safe for an address. All addresses are then considered url safe.
+ - isUrlSafe. Denotes a deprecated flag that is defined as URL-safe for an address. All addresses are then considered URL-safe.
2. _\[workchain_id - 1 byte]_ — The workchain ID (_workchain_id_) is defined by a signed 8-bit integer _workchain_id_.
(_0x00_ for the BaseChain, _0xff_ for the MasterChain)
-3. _\[account_id - 32 byte]_ — The account ID is made up of a ([big-endian](https://www.freecodecamp.org/news/what-is-endianness-big-endian-vs-little-endian/)) 256-bit address inside the workchain.
-4. _\[address verification - 2 bytes]_ — In user-friendly addresses, address verification is composed of a CRC16-CCITT signature from the previous 34 bytes. ([for example](https://github.com/andreypfau/ton-kotlin/blob/ce9595ec9e2ad0eb311351c8a270ef1bd2f4363e/ton-kotlin-crypto/common/src/crc32.kt))
- In fact, the idea pertaining to verification for user-friendly addresses is quite similar to the [Luhn algorithm](https://en.wikipedia.org/wiki/Luhn_algorithm) used in all bank cards to prevent the user from writing non-existing card numbers by mistake.
+3. _\[account_id - 32 byte]_ — The account ID is made up of a ([big-endian](https://www.freecodecamp.org/news/what-is-endianness-big-endian-vs-little-endian/)) 256-bit address in the workchain.
+4. _\[address verification - 2 bytes]_ — In user-friendly addresses, address verification is composed of a CRC16-CCITT signature from the previous 34 bytes. ([Example](https://github.com/andreypfau/ton-kotlin/blob/ce9595ec9e2ad0eb311351c8a270ef1bd2f4363e/ton-kotlin-crypto/common/src/crc32.kt))
+ In fact, the idea pertaining to verification for user-friendly addresses is quite similar to the [Luhn algorithm](https://en.wikipedia.org/wiki/Luhn_algorithm), which is used on all credit cards to prevent users from entering non-existing card numbers by mistake.
The addition of these 4 main components means that: `1 + 1 + 32 + 2 = 36` bytes in total (per user-friendly address).
@@ -112,12 +121,12 @@ To generate a user-friendly address, the developer must encode all 36 bytes usin
After this process is complete, the generation of a user-friendly address with a length of 48 non-spaced characters is finalized.
:::info DNS ADDRESS FLAGS
-On TON, DNS addresses such as mywallet.ton are sometimes used instead of raw and user-friendly addresses. In fact, DNS addresses are made up of user-friendly addresses and include all required flags that allow developers to access all flags from the DNS record within the TON domain.
+On TON, DNS addresses such as mywallet.ton are sometimes used instead of raw and user-friendly addresses. In fact, DNS addresses are made up of user-friendly addresses and include all the required flags that allow developers to access all the flags from the DNS record within the TON domain.
:::
#### User-Friendly Address Encoding Examples
-For example, a "test giver" smart contract (a special smart contract residing in the testnet masterchain that sends 2 test tokens to anyone who requests them) makes use of the following raw address:
+For example, the "test giver" smart contract (a special smart contract residing in the testnet masterchain that sends 2 test tokens to anyone who requests them) makes use of the following raw address:
`-1:fcb91a3a3816d0f7b8c2c76108b8a9bc5a6b7a55bd79f8ab101c52db29232260`
@@ -132,9 +141,9 @@ Notice that both forms (_base64_ and _base64url_) are valid and must be accepted
#### Bounceable vs Non-Bounceable Addresses
-The core idea behind the bounceable address flag is sender security.
+The core idea behind the bounceable address flag is sender's funds security.
-For example, if the destination smart contract does not exist, or if retrieval issues become apparent while processing the transaction, the message will be "bounced" back to the sender and constitute the remainder of the original value of the transaction (minus all transfer and gas fees). This ensures the sender doesn't lose their funds that were sent to an address that cannot accept the transaction.
+For example, if the destination smart contract does not exist, or if some issue happens during the transaction, the message will be "bounced" back to the sender and constitute the remainder of the original value of the transaction (minus all transfer and gas fees). This ensures the sender doesn't lose their funds that were sent by accident to an address that cannot accept the transaction.
In relation to bounceable addresses specifically:
@@ -145,7 +154,7 @@ Feel free to read more on this topic in our documentation to gain a better under
#### Armored base64 Representations
-Additional binary data related to TON Blockchain employs similar “armored” base64 user-friendly address representations. These differentiate from one another depending on the first 4 characters of their byte tag. For example, 256-bit Ed25519 public keys are represented by first creating a 36-byte sequence using the below process in order:
+Additional binary data related to TON Blockchain employs similar "armored" base64 user-friendly address representations. These differentiate from one another depending on the first 4 characters of their byte tag. For example, 256-bit Ed25519 public keys are represented by first creating a 36-byte sequence using the below process in order:
- A single byte tag using the _0x3E_ format denotes a public key
- A single byte tag using the _0xE6_ format denotes a Ed25519 public key
@@ -160,9 +169,10 @@ The resulting 36-byte sequence is converted into a 48-character base64 or base64
### Converting User-Friendly Addresses and Raw Addresses
-The simplest way to convert user-friendly and raw addresses is realized through the use of several TON APIs and other tools, including:
+The simplest way to convert user-friendly and raw addresses is to use one of several TON APIs and other tools, including:
* [ton.org/address](https://ton.org/address)
+* [dton.io API method](https://dton.io/api/address/0:867ac2b47d1955de6c8e23f57994fad507ea3bcfe2a7d76ff38f29ec46729627)
* [toncenter API methods in mainnet](https://toncenter.com/api/v2/#/accounts/pack_address_packAddress_get)
* [toncenter API methods in testnet](https://testnet.toncenter.com/api/v2/#/accounts/pack_address_packAddress_get)
@@ -173,3 +183,42 @@ Additionally, there are two ways to convert user-friendly and raw addresses for
It's also possible to make use of similar mechanisms using [SDKs](/develop/dapps/apis/sdk).
+### Address Examples
+
+Learn more examples on TON Addresses in the [TON Cookbook](/develop/dapps/cookbook#working-with-contracts-addresses).
+
+## Possible problems
+
+When interacting with the TON blockchain, it's crucial to understand the implications of transferring TON coins to `uninit` wallet addresses. This section outlines the various scenarios and their outcomes to provide clarity on how such transactions are handled.
+
+### What happens when you transfer Toncoin to an uninit address?
+
+#### Transaction with `state_init` included
+
+If you include the `state_init` (which consists of the wallet or smart contract's code and data) with your transaction. The smart contract is deployed first using the provided `state_init`. After deployment, the incoming message is processed, similar to sending to an already initialized account.
+
+#### Transaction without `state_init` and `bounce` flag set
+
+The message cannot be delivered to the `uninit` smart contract, and it will be bounced back to the sender. After deducting the consumed gas fees, the remaining amount is returned to the sender's address.
+
+#### Transaction without `state_init` and `bounce` flag unset
+
+The message cannot be delivered, but it will not bounce back to the sender. Instead, the sent amount will be credited to the receiving address, increasing its balance even though the wallet is not yet initialized. They will be stored there until the address holder deploys a smart wallet contract and then they can access the balance.
+
+#### How to do it right
+
+The best way to deploy a wallet is to send some TON to its address (which is not yet initialized) with the `bounce` flag cleared. After this step, the owner can deploy and initialize the wallet using funds at the current uninitialized address. This step usually occurs on the first wallet operation.
+
+### The TON blockchain implements protection against erroneous transactions
+
+In the TON blockchain, standard wallets and apps automatically manage the complexities of transactions to uninitialized addresses by using bounceable and non-bounceable address, which are described [here](#bounceable-vs-non-bounceable-addresses). It is common practice for wallets, when sending coins to non-initialized addresses, to send coins to both bounceable and non-bounceable addresses without return.
+
+If there is a need to quickly get an address in bounceable/non-bounceable form this can be done [here](https://ton.org/address/).
+
+### Responsibility for custom products
+
+If you are developing a custom product on the TON blockchain, it is essential to implement similar checks and logic:
+
+Ensure your application verifies whether the recipient address is initialized before sending funds.
+Based on the address state, use bounceable addresses for user smart contracts with custom application logic to ensure funds are returned. Use non-bounceable addresses for wallets.
+
diff --git a/docs/learn/overviews/blockchain-comparison.md b/docs/learn/overviews/blockchain-comparison.md
new file mode 100644
index 0000000000..0eb1397638
--- /dev/null
+++ b/docs/learn/overviews/blockchain-comparison.md
@@ -0,0 +1,10 @@
+# Comparison of Blockchains
+
+This document provides a comparative analysis of TON against Ethereum and Solana.
+
+| | Ethereum 2.0 (ETH 2.0) | Solana (SOL) | TON |
+|----------------------------|------------------------|------------------|------------------|
+| **Consensus** | Proof of Stake | Proof of History | BFT PoS |
+| **TPS** | 100,000 TPS | 59,400 TPS | 104,715 TPS |
+| **Block Time** | 12 sec | <1 sec | 5 sec |
+| **Time to Finalize Block** | 10-15 min | ~6.4 sec | < 6 sec |
diff --git a/docs/learn/overviews/cells.md b/docs/learn/overviews/cells.md
index c7ef762869..f5add736e0 100644
--- a/docs/learn/overviews/cells.md
+++ b/docs/learn/overviews/cells.md
@@ -28,7 +28,7 @@ For more on exotic cells see: [**TVM Whitepaper, Section 3**](https://ton.org/tv
A cell is an opaque object optimized for compact storage.
-In particular, it deduplicates data: if there are several eqivalent sub-cells referenced in different branches, their content is only stored once. However, opaqueness means that a cell cannot be modified or read directly. Thus, there are 2 additional flavors of the cells:
+In particular, it deduplicates data: if there are several equivalent sub-cells referenced in different branches, their content is only stored once. However, opaqueness means that a cell cannot be modified or read directly. Thus, there are 2 additional flavors of the cells:
* _Builder_ for partially constructed cells, for which fast operations for appending bitstrings, integers, other cells and references to other cells can be defined.
* _Slice_ for 'dissected' cells representing either the remainder of a partially parsed cell or a value (subcell) residing inside such a cell and extracted from it via a parsing instruction.
diff --git a/docs/learn/overviews/ton-blockchain.md b/docs/learn/overviews/ton-blockchain.md
index 3aaeadf2b0..e552267656 100644
--- a/docs/learn/overviews/ton-blockchain.md
+++ b/docs/learn/overviews/ton-blockchain.md
@@ -63,7 +63,7 @@ If you want to customize rules of the group of Shardchains, you could create a *
Theoretically, everyone in community can create own workchain. In fact, it's pretty complicated task to build it, after that to pay (expensive) price of creating it and receive 2/3 of votes from validators to approve creation of your Workchain.
-TON allows creating up to `2^30` workchains, each subdivided to up to `2^60` shards.
+TON allows creating up to `2^32` workchains, each subdivided to up to `2^60` shards.
Nowadays, there are only 2 workchains in TON: MasterChain and BaseChain.
diff --git a/docs/learn/tvm-instructions/fee-calculation-instructions.md b/docs/learn/tvm-instructions/fee-calculation-instructions.md
new file mode 100644
index 0000000000..ba55825884
--- /dev/null
+++ b/docs/learn/tvm-instructions/fee-calculation-instructions.md
@@ -0,0 +1,73 @@
+# TVM Upgrade 2024.04
+
+## Introduction of new instructions for cheap fee calculation
+
+:::tip
+This upgrade is active in mainnet since March 16 (see https://t.me/tonstatus/101). Preview of this update for blueprint is available in `@ton/sandbox@0.16.0-tvmbeta.3`, `@ton-community/func-js@0.6.3-tvmbeta.3` and `@ton-community/func-js-bin@0.4.5-tvmbeta.3` packages.
+:::
+
+This update is activated by Config8 `version` >= 6.
+
+## c7
+
+**c7** tuple extended from 14 to 16 elements:
+* **14**: tuple that contains some config parameters as cell slices. If the parameter is absent from the config, the value is null.
+ * **0**: `StoragePrices` from `ConfigParam 18`. Not the whole dict, but only the one StoragePrices entry that corresponds to the current time.
+ * **1**: `ConfigParam 19` (global id).
+ * **2**: `ConfigParam 20` (mc gas prices).
+ * **3**: `ConfigParam 21` (gas prices).
+ * **4**: `ConfigParam 24` (mc fwd fees).
+ * **5**: `ConfigParam 25` (fwd fees).
+ * **6**: `ConfigParam 43` (size limits).
+* **15**: "[due payment](https://github.com/ton-blockchain/ton/blob/8a9ff339927b22b72819c5125428b70c406da631/crypto/block/block.tlb#L237)" - current debt for storage fee (nanotons). Asm opcode: `DUEPAYMENT`.
+* **16**: "precompiled gas usage" - gas usage for the current contract if it is precompiled (see ConfigParam 45), null otherwise. Asm opcode: `GETPRECOMPILEDGAS`.
+
+The idea behind this extension of c7 by unpacked config parameters is the following: this data will be retrieved from global configuration by transaction executor, so it is already presented in memory of executor. However (before extension) smart-contract need to get all of these parameters one-by-one from configuration dictionary which is expensive and potentially unpredictable by gas (since cost depends on number of parameters).
+
+Due payment is needed so contract can properly assess storage fees: when message sent in default (bouncable) mode to smart-contract, storage fees are deducted (or added to due_payment field that contains storage fee related debt) prior message value is added to balance. Thus, if contract after processing message send gas excesses back with mode=64, that means that if contract balance hit 0, on next transactions storage fees start accruing in due_payment (and not deducted from incoming messages). That way debt will silently accumulate until account freezes. `DUEPAYMENT` allows developer explicitly account/withhold comission for storage and thus prevent any issues.
+
+
+## New opcodes
+
+### Opcodes to work with new c7 values
+26 gas for each, except for `SENDMSG` (because of cell operations).
+
+| xxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description |
+|:-|:--------------------|:-------------------------------------------------------------------------------------------------------------------------|
+| `UNPACKEDCONFIGTUPLE` | _`- c`_ | Retrieves tuple of configs slices from c7 |
+| `DUEPAYMENT` | _`- i`_ | Retrieves value of due payment from c7 |
+| `GLOBALID` | _`- i`_ | Now retrieves `ConfigParam 19` from from c7, ton form config dict. |
+| `SENDMSG` | _`msg mode - i`_ | Now retrieves `ConfigParam 24/25` (message prices) and `ConfigParam 43` (`max_msg_cells`) from c7, not from config dict. |
+
+### Opcodes to process config parameters
+
+The introduction of tuple of configurations slices in the TON transaction executor has made it more cost-effective to parse fee parameters. However, as new config parameters constructors may be introduced in the future, smart contracts may need to be updated to interpret these new parameters. To address this issue, special opcodes for fee calculation have been introduced. These opcodes read parameters from c7 and calculate fees in the same manner as the executor. With the introduction of new parameters constructors, these opcodes will be updated to accommodate the changes. This allows smart contracts to rely on these instructions for fee calculation without needing to interpret all types of constructors.
+
+26 gas for each.
+
+| xxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description |
+|:-|:-|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `GETGASFEE` | _`gas_used is_mc - price`_ | Calculates computation cost in nanotons for transaction that consumes _`gas_used`_ gas. |
+| `GETSTORAGEFEE` | _`cells bits seconds is_mc - price`_ | Calculates storage fees in nanotons for contract based on current storage prices. `cells` and `bits` are the size of the [`AccountState`](https://github.com/ton-blockchain/ton/blob/8a9ff339927b22b72819c5125428b70c406da631/crypto/block/block.tlb#L247) (with deduplication, including root cell). |
+| `GETFORWARDFEE` | _`cells bits is_mc - price`_ | Calculates forward fees in nanotons for outgoing message. _`is_mc`_ is true if the source or the destination is in masterchain, false if both are in basechain. Note, cells and bits in Message should be counted with account for deduplication and _root-is-not-counted_ rules. |
+| `GETPRECOMPILEDGAS` | _`- null`_ | reserved, currently returns `null`. Will return cost of contract execution in gas units if this contract is _precompiled_ |
+| `GETORIGINALFWDFEE` | _`fwd_fee is_mc - orig_fwd_fee`_ | calculate `fwd_fee * 2^16 / first_frac`. Can be used to get the original `fwd_fee` of the message (as replacement for hardcoded values like [this](https://github.com/ton-blockchain/token-contract/blob/21e7844fa6dbed34e0f4c70eb5f0824409640a30/ft/jetton-wallet.fc#L224C17-L224C46)) from `fwd_fee` parsed from incoming message. _`is_mc`_ is true if the source or the destination is in masterchain, false if both are in basechain. |
+| `GETGASFEESIMPLE` | _`gas_used is_mc - price`_ | Calculates additional computation cost in nanotons for transaction that consumes additional _`gas_used`_. In other words, same as `GETGASFEE`, but without flat price (just `(gas_used * price) / 2^16`). |
+| `GETFORWARDFEESIMPLE` | _`cells bits is_mc - price`_ | Calculates additional forward cost in nanotons for message that contains additional _`cells`_ and _`bits`_. In other words, same as `GETFORWARDFEE`, but without lump price (just `(bits*bit_price + cells*cell_price) / 2^16`). |
+
+`gas_used`, `cells`, `bits`, `time_delta` are integers in range `0..2^63-1`.
+
+### Cell level operations
+Operations for working with Merkle proofs, where cells can have non-zero level and multiple hashes.
+26 gas for each.
+
+| xxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description |
+|:-|:-|:--------------------------------------------------------------------|
+| `CLEVEL` | _`cell - level`_ | Returns level of the cell |
+| `CLEVELMASK` | _`cell - level_mask`_ | Returns level mask of the cell |
+| `i CHASHI` | _`cell - hash`_ | Returns `i`th hash of the cell|
+| `i CDEPTHI` | _`cell - depth`_ | Returns `i`th depth of the cell|
+| `CHASHIX` | _`cell i - depth`_ | Returns `i`th hash of the cell|
+| `CDEPTHIX` | _`cell i - depth`_ | Returns `i`th depth of the cell|
+
+`i` is in range `0..3`.
diff --git a/docs/learn/tvm-instructions/instructions.csv b/docs/learn/tvm-instructions/instructions.csv
index 63f06f94a3..3ff1b1b7d7 100644
--- a/docs/learn/tvm-instructions/instructions.csv
+++ b/docs/learn/tvm-instructions/instructions.csv
@@ -636,7 +636,7 @@ c4 POP",x -,26,"Sets the “global data root'' cell reference, thus allowing mod
SETCONTCTR,,#ED6 i:uint4,cont_registers,ED6i,"c[i] SETCONT
c[i] SETCONTCTR",x c - c',26,"Stores `x` into the savelist of continuation `c` as `c(i)`, and returns the resulting continuation `c'`. Almost all operations with continuations may be expressed in terms of `SETCONTCTR`, `POPCTR`, and `PUSHCTR`."
SETRETCTR,,#ED7 i:uint4,cont_registers,ED7i,c[i] SETRETCTR,x - ,26,Equivalent to `c0 PUSHCTR` `c[i] SETCONTCTR` `c0 POPCTR`.
-SETALTCTR,,#ED8 i:uint4,cont_registers,ED8i,c[i] SETALTCTR,x - ,26,Equivalent to `c1 PUSHCTR` `c[i] SETCONTCTR` `c0 POPCTR`.
+SETALTCTR,,#ED8 i:uint4,cont_registers,ED8i,c[i] SETALTCTR,x - ,26,Equivalent to `c1 PUSHCTR` `c[i] SETCONTCTR` `c1 POPCTR`.
POPSAVE,,#ED9 i:uint4,cont_registers,ED9i,"c[i] POPSAVE
c[i] POPCTRSAVE",x -,26,"Similar to `c[i] POPCTR`, but also saves the old value of `c[i]` into continuation `c0`.
Equivalent (up to exceptions) to `c[i] SAVECTR` `c[i] POPCTR`."
@@ -645,7 +645,7 @@ c[i] SAVECTR",,26,"Saves the current value of `c(i)` into the savelist of contin
SAVEALT,,#EDB i:uint4,cont_registers,EDBi,"c[i] SAVEALT
c[i] SAVEALTCTR",,26,"Similar to `c[i] SAVE`, but saves the current value of `c[i]` into the savelist of `c1`, not `c0`."
SAVEBOTH,,#EDC i:uint4,cont_registers,EDCi,"c[i] SAVEBOTH
-c[i] SAVEBOTHCTR",,26,Equivalent to `DUP` `c[i] SAVE` `c[i] SAVEALT`.
+c[i] SAVEBOTHCTR",,26,Equivalent to `c[i] SAVE` `c[i] SAVEALT`.
PUSHCTRX,,#EDE0,cont_registers,EDE0,PUSHCTRX,i - x,26,"Similar to `c[i] PUSHCTR`, but with `i`, `0 <= i <= 255`, taken from the stack.
Notice that this primitive is one of the few “exotic'' primitives, which are not polymorphic like stack manipulation primitives, and at the same time do not have well-defined types of parameters and return values, because the type of `x` depends on `i`."
POPCTRX,,#EDE1,cont_registers,EDE1,POPCTRX,x i - ,26,"Similar to `c[i] POPCTR`, but with `0 <= i <= 255` from the stack."
@@ -935,7 +935,7 @@ SENDRAWMSG,,#FB00,app_actions,FB00,SENDRAWMSG,c x - ,526,"Sends a raw message co
RAWRESERVE,,#FB02,app_actions,FB02,RAWRESERVE,x y - ,526,"Creates an output action which would reserve exactly `x` nanograms (if `y=0`), at most `x` nanograms (if `y=2`), or all but `x` nanograms (if `y=1` or `y=3`), from the remaining balance of the account. It is roughly equivalent to creating an outbound message carrying `x` nanograms (or `b-x` nanograms, where `b` is the remaining balance) to oneself, so that the subsequent output actions would not be able to spend more money than the remainder. Bit `+2` in `y` means that the external action does not fail if the specified amount cannot be reserved; instead, all remaining balance is reserved. Bit `+8` in `y` means `x:=-x` before performing any further actions. Bit `+4` in `y` means that `x` is increased by the original balance of the current account (before the compute phase), including all extra currencies, before performing any other checks and actions. Currently `x` must be a non-negative integer, and `y` must be in the range `0...15`."
RAWRESERVEX,,#FB03,app_actions,FB03,RAWRESERVEX,x D y - ,526,"Similar to `RAWRESERVE`, but also accepts a dictionary `D` (represented by a _Cell_ or _Null_) with extra currencies. In this way currencies other than Grams can be reserved."
SETCODE,,#FB04,app_actions,FB04,SETCODE,c - ,526,Creates an output action that would change this smart contract code to that given by _Cell_ `c`. Notice that this change will take effect only after the successful termination of the current run of the smart contract.
-SETLIBCODE,,#FB06,app_actions,FB06,SETLIBCODE,c x - ,526,"Creates an output action that would modify the collection of this smart contract libraries by adding or removing library with code given in _Cell_ `c`. If `x=0`, the library is actually removed if it was previously present in the collection (if not, this action does nothing). If `x=1`, the library is added as a private library, and if `x=2`, the library is added as a public library (and becomes available to all smart contracts if the current smart contract resides in the masterchain); if the library was present in the collection before, its public/private status is changed according to `x`. Values of `x` other than `0...2` are invalid."
+SETLIBCODE,,#FB06,app_actions,FB06,SETLIBCODE,c x - ,526,"Creates an output action that would modify the collection of this smart contract libraries by adding or removing library with code given in _Cell_ `c`. If `x=0`, the library is actually removed if it was previously present in the collection (if not, this action does nothing). If `x=1`, the library is added as a private library, and if `x=2`, the library is added as a public library (and becomes available to all smart contracts if the current smart contract resides in the masterchain); if the library was present in the collection before, its public/private status is changed according to `x`. Also, `16` can be added to `x` to enable bounce transaction on failure. Values of `x` other than `0...2 (+16 possible)` are invalid."
CHANGELIB,,#FB07,app_actions,FB07,CHANGELIB,h x - ,526,"Creates an output action similarly to `SETLIBCODE`, but instead of the library code accepts its hash as an unsigned 256-bit integer `h`. If `x!=0` and the library with hash `h` is absent from the library collection of this smart contract, this output action will fail."
DEBUG,,#FE nn:(#<= 239),debug,FEnn,{nn} DEBUG,-,26,`0 <= nn < 240`
DEBUGSTR,,#FEF n:(## 4) ssss:((n * 8 + 8) * Bit),debug,FEFnssss,"{string} DEBUGSTR
@@ -949,3 +949,78 @@ SETCP,,#FF nn:(#<= 239),codepage,FFnn,[nn] SETCP,-,26,"Selects TVM codepage `0 <
SETCP0,SETCP,#FF00,codepage,FF00,SETCP0,-,26,Selects TVM (test) codepage zero as described in this document.
SETCP_SPECIAL,,#FFF z:(## 4) {1 <= z},codepage,FFFz,[z-16] SETCP,-,26,"Selects TVM codepage `z-16` for `1 <= z <= 15`. Negative codepages `-13...-1` are reserved for restricted versions of TVM needed to validate runs of TVM in other codepages. Negative codepage `-14` is reserved for experimental codepages, not necessarily compatible between different TVM implementations, and should be disabled in the production versions of TVM."
SETCPX,,#FFF0,codepage,FFF0,SETCPX,c - ,26,Selects codepage `c` with `-2^15 <= c < 2^15` passed in the top of the stack.
+MYCODE,,#F8210,app_config,F8210,MYCODE,- c,26,Retrieves code of smart-contract from c7. Equivalent to `10 GETPARAM`.
+INCOMINGVALUE,,#F8211,app_config,F8211,INCOMINGVALUE,- t,26,Retrieves value of incoming message from c7. Equivalent to `11 GETPARAM`.
+STORAGEFEES,,#F8212,app_config,F8212,STORAGEFEES,- i,26,Retrieves value of storage phase fees from c7. Equivalent to `12 GETPARAM`.
+PREVBLOCKSINFOTUPLE,,#F8213,app_config,F8213,PREVBLOCKSINFOTUPLE,- t,26,Retrives PrevBlocksInfo: `[last_mc_blocks, prev_key_block]` from c7. Equivalent to `13 GETPARAM`.
+PREVMCBLOCKS,,#F83400,app_config,F83400,PREVMCBLOCKS,- t,34,Retrives `last_mc_blocks` part of PrevBlocksInfo from c7 (parameter 13).
+PREVKEYBLOCK,,#F83401,app_config,F83401,PREVKEYBLOCK,- t,34,Retrives `prev_key_block` part of PrevBlocksInfo from c7 (parameter 13).
+GLOBALID,,#F835,app_config,F835,GLOBALID,- i,26,Retrieves global_id from 19 network config.
+GASCONSUMED,,#F807,app_gas,F807,GASCONSUMED,- g_c,26,Returns gas consumed by VM so far (including this instruction).
+MULADDDIVMOD,,#A980,arithm_div,A980,MULADDDIVMOD,x y w z - q=floor((xy+w)/z) r=(xy+w)-zq,26,Performs multiplication, addition, division, and modulo in one step. Calculates q as floor((xy+w)/z) and r as (xy+w)-zq.
+MULADDDIVMODR,,#A981,arithm_div,A981,MULADDDIVMODR,x y w z - q=round((xy+w)/z) r=(xy+w)-zq,26,Similar to MULADDDIVMOD but calculates q as round((xy+w)/z).
+MULADDDIVMODC,,#A982,arithm_div,A982,MULADDDIVMODC,x y w z - q=ceil((xy+w)/z) r=(xy+w)-zq,26,Similar to MULADDDIVMOD but calculates q as ceil((xy+w)/z).
+ADDDIVMOD,,#A900,arithm_div,A900,ADDDIVMOD,x w z - q=floor((x+w)/z) r=(x+w)-zq,26,Performs addition, division, and modulo in one step. Calculates q as floor((x+w)/z) and r as (x+w)-zq.
+ADDDIVMODR,,#A901,arithm_div,A901,ADDDIVMODR,x w z - q=round((x+w)/z) r=(x+w)-zq,26,Similar to ADDDIVMOD but calculates q as round((x+w)/z).
+ADDDIVMODC,,#A902,arithm_div,A902,ADDDIVMODC,x w y - q=ceil((x+w)/z) r=(x+w)-zq,26,Similar to ADDDIVMOD but calculates q as ceil((x+w)/z). Incorrect stack description in the provided data; assumed typo for 'z' instead of 'y' in the input stack.
+ADDRSHIFTMOD,,#A920,arithm_div,A920,ADDRSHIFTMOD,x w z - q=floor((x+w)/2^z) r=(x+w)-q*2^z,26,Performs addition, right shift, and modulo in one step. Calculates q as floor((x+w)/2^z) and r as (x+w)-q*2^z.
+ADDRSHIFTMODR,,#A921,arithm_div,A921,ADDRSHIFTMODR,x w z - q=round((x+w)/2^z) r=(x+w)-q*2^z,26,Similar to ADDRSHIFTMOD but calculates q as round((x+w)/2^z).
+ADDRSHIFTMODC,,#A922,arithm_div,A922,ADDRSHIFTMODC,x w z - q=ceil((x+w)/2^z) r=(x+w)-q*2^z,26,Similar to ADDRSHIFTMOD but calculates q as ceil((x+w)/2^z).
+MULADDRSHIFTMOD,,#A9A0,arithm_div,A9A0,MULADDRSHIFTMOD,x y w z - q=floor((xy+w)/2^z) r=(xy+w)-q*2^z,26,Combines multiplication, addition, right shift, and modulo. Calculates q as floor((xy+w)/2^z) and r as (xy+w)-q*2^z.
+MULADDRSHIFTRMOD,,#A9A1,arithm_div,A9A1,MULADDRSHIFTRMOD,x y w z - q=round((xy+w)/2^z) r=(xy+w)-q*2^z,26,Similar to MULADDRSHIFTMOD but calculates q as round((xy+w)/2^z).
+MULADDRSHIFTCMOD,,#A9A2,arithm_div,A9A2,MULADDRSHIFTCMOD,x y w z - q=ceil((xy+w)/2^z) r=(xy+w)-q*2^z,26,Similar to MULADDRSHIFTMOD but calculates q as ceil((xy+w)/2^z).
+LSHIFTADDDIVMOD,,#A9D0 tt:uint8,arithm_div,A9D0tt,[tt+1] LSHIFT#ADDDIVMOD,x w z - q=floor((x*2^y+w)/z) r=(x*2^y+w)-zq,34,Performs left shift on x, adds w, then divides by z, rounding down for q and calculates remainder r.
+LSHIFTADDDIVMODR,,#A9D1 tt:uint8,arithm_div,A9D1tt,[tt+1] LSHIFT#ADDDIVMODR,x w z - q=round((x*2^y+w)/z) r=(x*2^y+w)-zq,34,Similar to LSHIFTADDDIVMOD but rounds q to the nearest integer.
+LSHIFTADDDIVMODC,,#A9D2 tt:uint8,arithm_div,A9D2tt,[tt+1] LSHIFT#ADDDIVMODC,x w z - q=ceil((x*2^y+w)/z) r=(x*2^y+w)-zq,34,Similar to LSHIFTADDDIVMOD but rounds q up to the nearest integer.
+HASHEXT_SHA256,,#F90400,app_crypto,F90400,HASHEXT_SHA256,s_1 ... s_n n - h,1/33 gas per byte,Calculates and returns hash of the concatenation of slices (or builders) `s_1...s_n`.
+HASHEXT_SHA512,,#F90401,app_crypto,F90401,HASHEXT_SHA512,s_1 ... s_n n - h,1/16 gas per byte,Calculates and returns hash of the concatenation of slices (or builders) `s_1...s_n`.
+HASHEXT_BLAKE2B,,#F90402,app_crypto,F90402,HASHEXT_BLAKE2B,s_1 ... s_n n - h,1/19 gas per byte,Calculates and returns hash of the concatenation of slices (or builders) `s_1...s_n`.
+HASHEXT_KECCAK256,,#F90403,app_crypto,F90403,HASHEXT_KECCAK256,s_1 ... s_n n - h,1/11 gas per byte,Calculates and returns hash of the concatenation of slices (or builders) `s_1...s_n`.
+HASHEXT_KECCAK512,,#F90404,app_crypto,F90404,HASHEXT_KECCAK512,s_1 ... s_n n - h,1/19 gas per byte,Calculates and returns hash of the concatenation of slices (or builders) `s_1...s_n`.
+HASHEXTR_SHA256,,#F90500,app_crypto,F90500,HASHEXTR_SHA256,s_n ... s_1 n - h,1/33 gas per byte,Same as `HASHEXT_`, but arguments are given in reverse order.
+HASHEXTR_SHA512,,#F90501,app_crypto,F90501,HASHEXTR_SHA512,s_n ... s_1 n - h,1/16 gas per byte,Same as `HASHEXT_`, but arguments are given in reverse order.
+HASHEXTR_BLAKE2B,,#F90502,app_crypto,F90502,HASHEXTR_BLAKE2B,s_n ... s_1 n - h,1/19 gas per byte,Same as `HASHEXT_`, but arguments are given in reverse order.
+HASHEXTR_KECCAK256,,#F90503,app_crypto,F90503,HASHEXTR_SHA256,s_n ... s_1 n - h,1/11 gas per byte,Same as `HASHEXT_`, but arguments are given in reverse order.
+HASHEXTR_KECCAK512,,#F90504,app_crypto,F90504,HASHEXTR_KECCAK512,s_n ... s_1 n - h,1/19 gas per byte,Same as `HASHEXT_`, but arguments are given in reverse order.
+HASHEXTA_SHA256,,#F90600,app_crypto,F90600,HASHEXTA_SHA256,b s_1 ... s_n n - b',1/33 gas per byte,Appends the resulting hash to a builder `b` instead of pushing it to the stack.
+HASHEXTA_SHA512,,#F90601,app_crypto,F90601,HASHEXTA_SHA512,b s_1 ... s_n n - b',1/16 gas per byte,Appends the resulting hash to a builder `b` instead of pushing it to the stack.
+HASHEXTA_BLAKE2B,,#F90602,app_crypto,F90602,HASHEXTA_BLAKE2B,b s_1 ... s_n n - b',1/19 gas per byte,Appends the resulting hash to a builder `b` instead of pushing it to the stack.
+HASHEXTA_KECCAK256,,#F90603,app_crypto,F90603,HASHEXTA_KECCAK256,b s_1 ... s_n n - b',1/11 gas per byte,Appends the resulting hash to a builder `b` instead of pushing it to the stack.
+HASHEXTA_KECCAK512,,#F90604,app_crypto,F90604,HASHEXTA_KECCAK512,b s_1 ... s_n n - b',1/6 gas per byte,Appends the resulting hash to a builder `b` instead of pushing it to the stack.
+HASHEXTAR_SHA256,,#F90700,app_crypto,F90700,HASHEXTAR_SHA256,b s_n ... s_1 n - b',1/33 gas per byte,Arguments are given in reverse order, appends hash to builder.
+HASHEXTAR_SHA512,,#F90701,app_crypto,F90701,HASHEXTAR_SHA512,b s_n ... s_1 n - b',1/16 gas per byte,Arguments are given in reverse order, appends hash to builder.
+HASHEXTAR_BLAKE2B,,#F90702,app_crypto,F90702,HASHEXTAR_BLAKE2B,b s_n ... s_1 n - b',1/19 gas per byte,Arguments are given in reverse order, appends hash to builder.
+HASHEXTAR_KECCAK256,,#F90703,app_crypto,F90703,HASHEXTAR_KECCAK256,b s_n ... s_1 n - b',1/11 gas per byte,Arguments are given in reverse order, appends hash to builder.
+HASHEXTAR_KECCAK512,,#F90704,app_crypto,F90704,HASHEXTAR_KECCAK512,b s_n ... s_1 n - b',1/6 gas per byte,Arguments are given in reverse order, appends hash to builder.
+ECRECOVER,,#F912,app_crypto,F912,ECRECOVER,hash v r s - 0 or h x1 x2 -1,1526,Recovers public key from signature, identical to Bitcoin/Ethereum operations.
+P256_CHKSIGNS,,#F915,app_crypto,F915,P256_CHKSIGNS,d sig k - ?,3526,Checks seck256r1-signature `sig` of data portion of slice `d` and public key `k`. Returns -1 on success, 0 on failure.
+P256_CHKSIGNU,,#F914,app_crypto,F914,P256_CHKSIGNU,h sig k - ?,3526,Same as P256_CHKSIGNS, but the signed data is 32-byte encoding of 256-bit unsigned integer h.
+RIST255_FROMHASH,,#F920,app_crypto,F920,RIST255_FROMHASH,h1 h2 - x,626,Deterministically generates a valid point `x` from a 512-bit hash (given as two 256-bit integers).
+RIST255_VALIDATE,,#F921,app_crypto,F921,RIST255_VALIDATE,x - ,226,Checks that integer `x` is a valid representation of some curve point. Throws `range_chk` on error.
+RIST255_ADD,,#F922,app_crypto,F922,RIST255_ADD,x y - x+y,626,Addition of two points on a curve.
+RIST255_SUB,,#F923,app_crypto,F923,RIST255_SUB,x y - x-y,626,Subtraction of two points on curve.
+RIST255_MUL,,#F924,app_crypto,F924,RIST255_MUL,x n - x*n,2026,Multiplies point `x` by a scalar `n`. Any `n` is valid, including negative.
+RIST255_MULBASE,,#F925,app_crypto,F925,RIST255_MULBASE,n - g*n,776,Multiplies the generator point `g` by a scalar `n`. Any `n` is valid, including negative.
+RIST255_PUSHL,,#F926,app_crypto,F926,RIST255_PUSHL,- l,26,Pushes integer `l=2^252+27742317777372353535851937790883648493`, which is the order of the group.
+RIST255_QVALIDATE,,#B7F921,app_crypto,B7F921,RIST255_QVALIDATE,x - 0 or -1,234,Quiet version of `RIST255_VALIDATE`.
+RIST255_QADD,,#B7F922,app_crypto,B7F922,RIST255_QADD,x y - 0 or x+y -1,634,Quiet version of `RIST255_ADD`.
+RIST255_QSUB,,#B7F923,app_crypto,B7F923,RIST255_QSUB,x y - 0 or x-y -1,634,Quiet version of `RIST255_SUB`.
+RIST255_QMUL,,#B7F924,app_crypto,B7F924,RIST255_QMUL,x n - 0 or x*n -1,2034,Quiet version of `RIST255_MUL`.
+RIST255_QMULBASE,,#B7F925,app_crypto,B7F925,RIST255_QMULBASE,n - 0 or g*n -1,784,Quiet version of `RIST255_MULBASE`
+RUNVM,,#DB4 flags:(## 12),cont_basic,DB4fff,RUNVM,x_1 ... x_n n code [r] [c4] [c7] [g_l] [g_m] - x'_1 ... x'_m exitcode [data'] [c4'] [c5] [g_c],66+x,Runs child VM with code `code` and stack `x_1...x_n`. Returns the resulting stack `x'_1...x'_m` and exitcode. Other arguments and return values are enabled by flags.
+RUNVMX,,#DB50,cont_basic,DB50,RUNVMX,x_1 ... x_n n code [r] [c4] [c7] [g_l] [g_m] flags - x'_1 ... x'_m exitcode [data'] [c4'] [c5] [g_c],66+x,Same as `RUNVM`, but pops flags from stack.
+GETGASFEE,,#F836,app_config,F836,GETGASFEE,gas_used is_mc - price,,Calculates gas fee
+GETSTORAGEFEE,,#F837,app_config,F837,GETSTORAGEFEE,cells bits seconds is_mc - price,,Calculates storage fees in nanotons for contract based on current storage prices. `cells` and `bits` are the size of the [AccountState](https://github.com/ton-blockchain/ton/blob/8a9ff339927b22b72819c5125428b70c406da631/crypto/block/block.tlb#L247) (with deduplication, including root cell).
+GETFORWARDFEE,,#F838,app_config,F838,GETFORWARDFEE,cells bits is_mc - price,,Calculates forward fees in nanotons for outgoing message. `is_mc` is true if the source or the destination is in masterchain, false if both are in basechain. Note, cells and bits in Message should be counted with account for deduplication and root-is-not-counted rules.
+GETPRECOMPILEDGAS,,#F839,app_config,F839,GETPRECOMPILEDGAS,- x,,reserved, currently returns null. Will return cost of contract execution in gas units if this contract is precompiled
+GETORIGINALFWDFEE,,#F83A,app_config,F83A,GETORIGINALFWDFEE,fwd_fee is_mc - orig_fwd_fee,,calculate `fwd_fee * 2^16 / first_frac`. Can be used to get the original `fwd_fee` of the message (as replacement for hardcoded values like [this](https://github.com/ton-blockchain/token-contract/blob/21e7844fa6dbed34e0f4c70eb5f0824409640a30/ft/jetton-wallet.fc#L224C17-L224C46)) from `fwd_fee` parsed from incoming message. `is_mc` is true if the source or the destination is in masterchain, false if both are in basechain.
+GETGASFEESIMPLE,,#F83B,app_config,F83B,GETGASFEESIMPLE,gas_used is_mc - price,,Same as `GETGASFEE`, but without flat price (just `(gas_used * price) / 2^16)`.
+GETFORWARDFEESIMPLE,,#F83C,app_config,F83C,GETFORWARDFEESIMPLE,cells bits is_mc - price,,Calculates additional forward cost in nanotons for message that contains additional `cells` and `bits`. In other words, same as `GETFORWARDFEE`, but without lump price (just `(bits*bit_price + cells*cell_price) / 2^16)`.
+UNPACKEDCONFIGTUPLE,,#F82E,app_config,F82E,UNPACKEDCONFIGTUPLE,- c,26,Retrieves tuple of configs slices from c7
+DUEPAYMENT,,#F82F,app_config,F82F,DUEPAYMENT,- i,26,Retrieves value of due payment from c7
+GLOBALID,,#F835,app_config,F835,GLOBALID,- i,26,Now retrieves `ConfigParam 19` from from c7, ton form config dict.
+SENDMSG,,#FB08,app_config,FB08,SENDMSG,msg mode - i,,Now retrieves `ConfigParam 24/25` (message prices) and `ConfigParam 43` (`max_msg_cells`) from c7, not from config dict.
+CLEVEL,,#D766,cell_parse,D766,CLEVEL,cell - level,26,Returns level of the cell
+CLEVELMASK,,#D767,cell_parse,D767,CLEVELMASK,cell - level_mask,26,Returns level mask of the cell
+CHASHIX,,#D770,cell_parse,D770,CHASHIX,cell i - depth,26,Returns ith hash of the cell (i is in range 0..3)
+CDEPTHIX,,#D771,cell_parse,D771,CDEPTHIX,cell i - depth,26,Returns ith depth of the cell (i is in range 0..3)
diff --git a/docs/learn/tvm-instructions/instructions.mdx b/docs/learn/tvm-instructions/instructions.mdx
deleted file mode 100644
index 1a2bdf98bc..0000000000
--- a/docs/learn/tvm-instructions/instructions.mdx
+++ /dev/null
@@ -1,982 +0,0 @@
-import { SearchField } from '@site/src/components/SearchField';
-import { opcodes } from '@site/src/data/opcodes';
-
-# TVM Instructions
-
-:::caution advanced level
-This information is **very low-level** and could be hard to understand for newcomers.
-:::
-
-## Introduction
-This document provides a list of TVM instructions along with their opcodes and mnemonics.
-
-:::info
-[**TVM.pdf**](https://ton.org/tvm.pdf) document contains a full description of TON Virtual Machine.
-:::
-
-Fift is a stack-based programming language designed to manage TON smart contracts. The Fift assembler is a Fift library that converts mnemonics of TVM instructions into their binary representation.
-
-A description of Fift, including an introduction to the Fift assembler, can be found [here](https://github.com/Piterden/TON-docs/blob/master/Fift.%20A%20Brief%20Introduction.md).
-
-This document specifies the corresponding mnemonic for each instruction.
-
-Note the following:
-
-1. Fift is a stack-based language, therefore all the arguments of any instruction are written before it (e.g. [`5 PUSHINT`](#instr-pushint-4), [`s0 s4 XCHG`](#instr-xchg-ij)).
-2. Stack registers are denoted by `s0, s1, ..., s15`. Other stack registers (up to 255) are denoted by `i s()` (e.g. `100 s()`).
-3. Control registers are denoted by `c0, c1, ..., c15`.
-
-### Gas prices
-The gas price of each instruction is specified in this document. The basic gas price of an instruction is `10 + b`, where `b` is the instruction length in bits. Some operations have additional fees:
-1. _Parsing cells_: Transforming a cell into a slice costs **100 gas units** if the cell is loading for the first time and **25** for subsequent loads during the same transaction. For such instructions, two gas prices are specified (e.g. [`CTOS`](#instr-ctos): `118/43`).
-2. _Cell creation_: **500 gas units**.
-3. _Throwing exceptions_: **50 gas units**. In this document the exception fee is only specified for an instruction if its primary purpose is to throw (e.g. [`THROWIF`](#instr-throwif-short), [`FITS`](#instr-fits)). If the instruction only throws in some cases, two gas prices are specified (e.g. [`FITS`](#instr-fits): `26/76`).
-4. _Tuple creation_: **1 gas unit** for every tuple element.
-5. _Implicit jumps_: **10 gas units** for an implicit jump, **5 gas units** for an implicit back jump. This fee is not a part of any instruction.
-6. _Moving stack elements between continuations_: **1 gas unit** per element, however moving the first 32 elements is free.
-
-
-### Quick search
-
-:::info
-
-A full machine-readable list of TVM instructions is available [here](https://github.com/ton-community/ton-docs/blob/main/docs/learn/tvm-instructions/instructions.csv).
-:::
-
-Feel free to use the search field below to find a specific instruction:
-
-
-
-## 2 Stack manipulation primitives
-
-Here `0 <= i,j,k <= 15` if not stated otherwise.
-
-### 2.1 Basic stack manipulation primitives
-| xxxxxxx Opcode | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description | xxxx Gas |
-|:-|:-|:-|:-|:-|
-| **`00`** | `NOP` | _`-`_ | Does nothing. | `18` |
-| **`01`** | `SWAP` | _`x y - y x`_ | Same as [`s1 XCHG0`](#instr-xchg-0i). | `18` |
-| **`0i`** | `s[i] XCHG0` | | Interchanges `s0` with `s[i]`, `1 <= i <= 15`. | `18` |
-| **`10ij`** | `s[i] s[j] XCHG` | | Interchanges `s[i]` with `s[j]`, `1 <= i < j <= 15`. | `26` |
-| **`11ii`** | `s0 [ii] s() XCHG` | | Interchanges `s0` with `s[ii]`, `0 <= ii <= 255`. | `26` |
-| **`1i`** | `s1 s[i] XCHG` | | Interchanges `s1` with `s[i]`, `2 <= i <= 15`. | `18` |
-| **`2i`** | `s[i] PUSH` | | Pushes a copy of the old `s[i]` into the stack. | `18` |
-| **`20`** | `DUP` | _`x - x x`_ | Same as [`s0 PUSH`](#instr-push). | `18` |
-| **`21`** | `OVER` | _`x y - x y x`_ | Same as [`s1 PUSH`](#instr-push). | `18` |
-| **`3i`** | `s[i] POP` | | Pops the old `s0` value into the old `s[i]`. Equivalent to [`s[i] XCHG0`](#instr-xchg-0i) [`DROP`](#instr-drop) | `18` |
-| **`30`** | `DROP` | _`x -`_ | Same as [`s0 POP`](#instr-pop), discards the top-of-stack value. | `18` |
-| **`31`** | `NIP` | _`x y - y`_ | Same as [`s1 POP`](#instr-pop). | `18` |
-### 2.2 Complex stack manipulation primitives
-| xxxxxxx Opcode | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description | xxxx Gas |
-|:-|:-|:-|:-|:-|
-| **`4ijk`** | `s[i] s[j] s[k] XCHG3` | | Equivalent to [`s2 s[i] XCHG`](#instr-xchg-ij) [`s1 s[j] XCHG`](#instr-xchg-ij) [`s[k] XCHG0`](#instr-xchg-0i). | `26` |
-| **`50ij`** | `s[i] s[j] XCHG2` | | Equivalent to [`s1 s[i] XCHG`](#instr-xchg-ij) [`s[j] XCHG0`](#instr-xchg-0i). | `26` |
-| **`51ij`** | `s[i] s[j] XCPU` | | Equivalent to [`s[i] XCHG0`](#instr-xchg-0i) [`s[j] PUSH`](#instr-push). | `26` |
-| **`52ij`** | `s[i] s[j-1] PUXC` | | Equivalent to [`s[i] PUSH`](#instr-push) [`SWAP`](#instr-swap) [`s[j] XCHG0`](#instr-xchg-0i). | `26` |
-| **`53ij`** | `s[i] s[j] PUSH2` | | Equivalent to [`s[i] PUSH`](#instr-push) [`s[j+1] PUSH`](#instr-push). | `26` |
-| **`540ijk`** | `s[i] s[j] s[k] XCHG3_l` | | Long form of [`XCHG3`](#instr-xchg3). | `34` |
-| 541ijk | `s[i] s[j] s[k] XC2PU` | | Equivalent to [`s[i] s[j] XCHG2`](#instr-xchg2) [`s[k] PUSH`](#instr-push). | `34` |
-| **`542ijk`** | `s[i] s[j] s[k-1] XCPUXC` | | Equivalent to [`s1 s[i] XCHG`](#instr-xchg-ij) [`s[j] s[k-1] PUXC`](#instr-puxc). | `34` |
-| **`543ijk`** | `s[i] s[j] s[k] XCPU2` | | Equivalent to [`s[i] XCHG0`](#instr-xchg-0i) [`s[j] s[k] PUSH2`](#instr-push2). | `34` |
-| **`544ijk`** | `s[i] s[j-1] s[k-1] PUXC2` | | Equivalent to [`s[i] PUSH`](#instr-push) [`s2 XCHG0`](#instr-xchg-0i) [`s[j] s[k] XCHG2`](#instr-xchg2). | `34` |
-| **`545ijk`** | `s[i] s[j-1] s[k-1] PUXCPU` | | Equivalent to [`s[i] s[j-1] PUXC`](#instr-puxc) [`s[k] PUSH`](#instr-push). | `34` |
-| **`546ijk`** | `s[i] s[j-1] s[k-2] PU2XC` | | Equivalent to [`s[i] PUSH`](#instr-push) [`SWAP`](#instr-swap) [`s[j] s[k-1] PUXC`](#instr-puxc). | `34` |
-| **`547ijk`** | `s[i] s[j] s[k] PUSH3` | | Equivalent to [`s[i] PUSH`](#instr-push) [`s[j+1] s[k+1] PUSH2`](#instr-push2). | `34` |
-| **`55ij`** | `[i+1] [j+1] BLKSWAP` | | Permutes two blocks `s[j+i+1] … s[j+1]` and `s[j] … s0`. `0 <= i,j <= 15` Equivalent to [`[i+1] [j+1] REVERSE`](#instr-reverse) [`[j+1] 0 REVERSE`](#instr-reverse) [`[i+j+2] 0 REVERSE`](#instr-reverse). | `26` |
-| **`5513`** | `ROT2` `2ROT` | _`a b c d e f - c d e f a b`_ | Rotates the three topmost pairs of stack entries. | `26` |
-| **`550i`** | `[i+1] ROLL` | | Rotates the top `i+1` stack entries. Equivalent to [`1 [i+1] BLKSWAP`](#instr-blkswap). | `26` |
-| **`55i0`** | `[i+1] -ROLL` `[i+1] ROLLREV` | | Rotates the top `i+1` stack entries in the other direction. Equivalent to [`[i+1] 1 BLKSWAP`](#instr-blkswap). | `26` |
-| **`56ii`** | `[ii] s() PUSH` | | Pushes a copy of the old `s[ii]` into the stack. `0 <= ii <= 255` | `26` |
-| **`57ii`** | `[ii] s() POP` | | Pops the old `s0` value into the old `s[ii]`. `0 <= ii <= 255` | `26` |
-| **`58`** | `ROT` | _`a b c - b c a`_ | Equivalent to [`1 2 BLKSWAP`](#instr-blkswap) or to [`s2 s1 XCHG2`](#instr-xchg2). | `18` |
-| **`59`** | `ROTREV` `-ROT` | _`a b c - c a b`_ | Equivalent to [`2 1 BLKSWAP`](#instr-blkswap) or to [`s2 s2 XCHG2`](#instr-xchg2). | `18` |
-| **`5A`** | `SWAP2` `2SWAP` | _`a b c d - c d a b`_ | Equivalent to [`2 2 BLKSWAP`](#instr-blkswap) or to [`s3 s2 XCHG2`](#instr-xchg2). | `18` |
-| **`5B`** | `DROP2` `2DROP` | _`a b - `_ | Equivalent to [`DROP`](#instr-drop) [`DROP`](#instr-drop). | `18` |
-| **`5C`** | `DUP2` `2DUP` | _`a b - a b a b`_ | Equivalent to [`s1 s0 PUSH2`](#instr-push2). | `18` |
-| **`5D`** | `OVER2` `2OVER` | _`a b c d - a b c d a b`_ | Equivalent to [`s3 s2 PUSH2`](#instr-push2). | `18` |
-| **`5Eij`** | `[i+2] [j] REVERSE` | | Reverses the order of `s[j+i+1] … s[j]`. | `26` |
-| **`5F0i`** | `[i] BLKDROP` | | Equivalent to [`DROP`](#instr-drop) performed `i` times. | `26` |
-| **`5Fij`** | `[i] [j] BLKPUSH` | | Equivalent to `PUSH s(j)` performed `i` times. `1 <= i <= 15`, `0 <= j <= 15`. | `26` |
-| **`60`** | `PICK` `PUSHX` | | Pops integer `i` from the stack, then performs [`s[i] PUSH`](#instr-push). | `18` |
-| **`61`** | `ROLLX` | | Pops integer `i` from the stack, then performs [`1 [i] BLKSWAP`](#instr-blkswap). | `18` |
-| **`62`** | `-ROLLX` `ROLLREVX` | | Pops integer `i` from the stack, then performs [`[i] 1 BLKSWAP`](#instr-blkswap). | `18` |
-| **`63`** | `BLKSWX` | | Pops integers `i`,`j` from the stack, then performs [`[i] [j] BLKSWAP`](#instr-blkswap). | `18` |
-| **`64`** | `REVX` | | Pops integers `i`,`j` from the stack, then performs [`[i] [j] REVERSE`](#instr-reverse). | `18` |
-| **`65`** | `DROPX` | | Pops integer `i` from the stack, then performs [`[i] BLKDROP`](#instr-blkdrop). | `18` |
-| **`66`** | `TUCK` | _`a b - b a b`_ | Equivalent to [`SWAP`](#instr-swap) [`OVER`](#instr-over) or to [`s1 s1 XCPU`](#instr-xcpu). | `18` |
-| **`67`** | `XCHGX` | | Pops integer `i` from the stack, then performs [`s[i] XCHG`](#instr-xchg-ij). | `18` |
-| **`68`** | `DEPTH` | _`- depth`_ | Pushes the current depth of the stack. | `18` |
-| **`69`** | `CHKDEPTH` | _`i -`_ | Pops integer `i` from the stack, then checks whether there are at least `i` elements, generating a stack underflow exception otherwise. | `18/58` |
-| **`6A`** | `ONLYTOPX` | | Pops integer `i` from the stack, then removes all but the top `i` elements. | `18` |
-| **`6B`** | `ONLYX` | | Pops integer `i` from the stack, then leaves only the bottom `i` elements. Approximately equivalent to [`DEPTH`](#instr-depth) [`SWAP`](#instr-swap) [`SUB`](#instr-sub) [`DROPX`](#instr-dropx). | `18` |
-| **`6Cij`** | `[i] [j] BLKDROP2` | | Drops `i` stack elements under the top `j` elements. `1 <= i <= 15`, `0 <= j <= 15` Equivalent to [`[i+j] 0 REVERSE`](#instr-reverse) [`[i] BLKDROP`](#instr-blkdrop) [`[j] 0 REVERSE`](#instr-reverse). | `26` |
-
-## 3 Tuple, List, and Null primitives
-| xxxxxxx Opcode | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description | xxxx Gas |
-|:-|:-|:-|:-|:-|
-| **`6D`** | `NULL` `PUSHNULL` | _` - null`_ | Pushes the only value of type _Null_. | `18` |
-| **`6E`** | `ISNULL` | _`x - ?`_ | Checks whether `x` is a _Null_, and returns `-1` or `0` accordingly. | `18` |
-| **`6F0n`** | `[n] TUPLE` | _`x_1 ... x_n - t`_ | Creates a new _Tuple_ `t=(x_1, … ,x_n)` containing `n` values `x_1`,..., `x_n`. `0 <= n <= 15` | `26+n` |
-| **`6F00`** | `NIL` | _`- t`_ | Pushes the only _Tuple_ `t=()` of length zero. | `26` |
-| **`6F01`** | `SINGLE` | _`x - t`_ | Creates a singleton `t:=(x)`, i.e., a _Tuple_ of length one. | `27` |
-| **`6F02`** | `PAIR` `CONS` | _`x y - t`_ | Creates pair `t:=(x,y)`. | `28` |
-| **`6F03`** | `TRIPLE` | _`x y z - t`_ | Creates triple `t:=(x,y,z)`. | `29` |
-| **`6F1k`** | `[k] INDEX` | _`t - x`_ | Returns the `k`-th element of a _Tuple_ `t`. `0 <= k <= 15`. | `26` |
-| **`6F10`** | `FIRST` `CAR` | _`t - x`_ | Returns the first element of a _Tuple_. | `26` |
-| **`6F11`** | `SECOND` `CDR` | _`t - y`_ | Returns the second element of a _Tuple_. | `26` |
-| **`6F12`** | `THIRD` | _`t - z`_ | Returns the third element of a _Tuple_. | `26` |
-| **`6F2n`** | `[n] UNTUPLE` | _`t - x_1 ... x_n`_ | Unpacks a _Tuple_ `t=(x_1,...,x_n)` of length equal to `0 <= n <= 15`. If `t` is not a _Tuple_, or if `\|t\| != n`, a type check exception is thrown. | `26+n` |
-| **`6F21`** | `UNSINGLE` | _`t - x`_ | Unpacks a singleton `t=(x)`. | `27` |
-| **`6F22`** | `UNPAIR` `UNCONS` | _`t - x y`_ | Unpacks a pair `t=(x,y)`. | `28` |
-| **`6F23`** | `UNTRIPLE` | _`t - x y z`_ | Unpacks a triple `t=(x,y,z)`. | `29` |
-| **`6F3k`** | `[k] UNPACKFIRST` | _`t - x_1 ... x_k`_ | Unpacks first `0 <= k <= 15` elements of a _Tuple_ `t`. If `\|t\| `0 <= k <= 15` If `k >= \|t\|`, throws a range check exception. | `26+\|t\|` |
-| **`6F50`** | `SETFIRST` | _`t x - t'`_ | Sets the first component of _Tuple_ `t` to `x` and returns the resulting _Tuple_ `t'`. | `26+\|t\|` |
-| **`6F51`** | `SETSECOND` | _`t x - t'`_ | Sets the second component of _Tuple_ `t` to `x` and returns the resulting _Tuple_ `t'`. | `26+\|t\|` |
-| **`6F52`** | `SETTHIRD` | _`t x - t'`_ | Sets the third component of _Tuple_ `t` to `x` and returns the resulting _Tuple_ `t'`. | `26+\|t\|` |
-| **`6F6k`** | `[k] INDEXQ` | _`t - x`_ | Returns the `k`-th element of a _Tuple_ `t`, where `0 <= k <= 15`. In other words, returns `x_{k+1}` if `t=(x_1,...,x_n)`. If `k>=n`, or if `t` is _Null_, returns a _Null_ instead of `x`. | `26` |
-| **`6F60`** | `FIRSTQ` `CARQ` | _`t - x`_ | Returns the first element of a _Tuple_. | `26` |
-| **`6F61`** | `SECONDQ` `CDRQ` | _`t - y`_ | Returns the second element of a _Tuple_. | `26` |
-| **`6F62`** | `THIRDQ` | _`t - z`_ | Returns the third element of a _Tuple_. | `26` |
-| **`6F7k`** | `[k] SETINDEXQ` | _`t x - t'`_ | Sets the `k`-th component of _Tuple_ `t` to `x`, where `0 <= k < 16`, and returns the resulting _Tuple_ `t'`. If `\|t\| <= k`, first extends the original _Tuple_ to length `n’=k+1` by setting all new components to _Null_. If the original value of `t` is _Null_, treats it as an empty _Tuple_. If `t` is not _Null_ or _Tuple_, throws an exception. If `x` is _Null_ and either `\|t\| <= k` or `t` is _Null_, then always returns `t'=t` (and does not consume tuple creation gas). | `26+\|t’\|` |
-| **`6F70`** | `SETFIRSTQ` | _`t x - t'`_ | Sets the first component of _Tuple_ `t` to `x` and returns the resulting _Tuple_ `t'`. | `26+\|t’\|` |
-| **`6F71`** | `SETSECONDQ` | _`t x - t'`_ | Sets the second component of _Tuple_ `t` to `x` and returns the resulting _Tuple_ `t'`. | `26+\|t’\|` |
-| **`6F72`** | `SETTHIRDQ` | _`t x - t'`_ | Sets the third component of _Tuple_ `t` to `x` and returns the resulting _Tuple_ `t'`. | `26+\|t’\|` |
-| **`6F80`** | `TUPLEVAR` | _`x_1 ... x_n n - t`_ | Creates a new _Tuple_ `t` of length `n` similarly to [`TUPLE`](#instr-tuple), but with `0 <= n <= 255` taken from the stack. | `26+n` |
-| **`6F81`** | `INDEXVAR` | _`t k - x`_ | Similar to [`k INDEX`](#instr-index), but with `0 <= k <= 254` taken from the stack. | `26` |
-| **`6F82`** | `UNTUPLEVAR` | _`t n - x_1 ... x_n`_ | Similar to [`n UNTUPLE`](#instr-untuple), but with `0 <= n <= 255` taken from the stack. | `26+n` |
-| **`6F83`** | `UNPACKFIRSTVAR` | _`t n - x_1 ... x_n`_ | Similar to [`n UNPACKFIRST`](#instr-unpackfirst), but with `0 <= n <= 255` taken from the stack. | `26+n` |
-| **`6F84`** | `EXPLODEVAR` | _`t n - x_1 ... x_m m`_ | Similar to [`n EXPLODE`](#instr-explode), but with `0 <= n <= 255` taken from the stack. | `26+m` |
-| **`6F85`** | `SETINDEXVAR` | _`t x k - t'`_ | Similar to [`k SETINDEX`](#instr-setindex), but with `0 <= k <= 254` taken from the stack. | `26+\|t’\|` |
-| **`6F86`** | `INDEXVARQ` | _`t k - x`_ | Similar to [`n INDEXQ`](#instr-indexq), but with `0 <= k <= 254` taken from the stack. | `26` |
-| **`6F87`** | `SETINDEXVARQ` | _`t x k - t'`_ | Similar to [`k SETINDEXQ`](#instr-setindexq), but with `0 <= k <= 254` taken from the stack. | `26+\|t’\|` |
-| **`6F88`** | `TLEN` | _`t - n`_ | Returns the length of a _Tuple_. | `26` |
-| **`6F89`** | `QTLEN` | _`t - n or -1`_ | Similar to [`TLEN`](#instr-tlen), but returns `-1` if `t` is not a _Tuple_. | `26` |
-| **`6F8A`** | `ISTUPLE` | _`t - ?`_ | Returns `-1` or `0` depending on whether `t` is a _Tuple_. | `26` |
-| **`6F8B`** | `LAST` | _`t - x`_ | Returns the last element of a non-empty _Tuple_ `t`. | `26` |
-| **`6F8C`** | `TPUSH` `COMMA` | _`t x - t'`_ | Appends a value `x` to a _Tuple_ `t=(x_1,...,x_n)`, but only if the resulting _Tuple_ `t'=(x_1,...,x_n,x)` is of length at most 255. Otherwise throws a type check exception. | `26+\|t’\|` |
-| **`6F8D`** | `TPOP` | _`t - t' x`_ | Detaches the last element `x=x_n` from a non-empty _Tuple_ `t=(x_1,...,x_n)`, and returns both the resulting _Tuple_ `t'=(x_1,...,x_{n-1})` and the original last element `x`. | `26+\|t’\|` |
-| **`6FA0`** | `NULLSWAPIF` | _`x - x or null x`_ | Pushes a _Null_ under the topmost _Integer_ `x`, but only if `x!=0`. | `26` |
-| **`6FA1`** | `NULLSWAPIFNOT` | _`x - x or null x`_ | Pushes a _Null_ under the topmost _Integer_ `x`, but only if `x=0`. May be used for stack alignment after quiet primitives such as [`PLDUXQ`](#instr-plduxq). | `26` |
-| **`6FA2`** | `NULLROTRIF` | _`x y - x y or null x y`_ | Pushes a _Null_ under the second stack entry from the top, but only if the topmost _Integer_ `y` is non-zero. | `26` |
-| **`6FA3`** | `NULLROTRIFNOT` | _`x y - x y or null x y`_ | Pushes a _Null_ under the second stack entry from the top, but only if the topmost _Integer_ `y` is zero. May be used for stack alignment after quiet primitives such as [`LDUXQ`](#instr-lduxq). | `26` |
-| **`6FA4`** | `NULLSWAPIF2` | _`x - x or null null x`_ | Pushes two nulls under the topmost _Integer_ `x`, but only if `x!=0`. Equivalent to [`NULLSWAPIF`](#instr-nullswapif) [`NULLSWAPIF`](#instr-nullswapif). | `26` |
-| **`6FA5`** | `NULLSWAPIFNOT2` | _`x - x or null null x`_ | Pushes two nulls under the topmost _Integer_ `x`, but only if `x=0`. Equivalent to [`NULLSWAPIFNOT`](#instr-nullswapifnot) [`NULLSWAPIFNOT`](#instr-nullswapifnot). | `26` |
-| **`6FA6`** | `NULLROTRIF2` | _`x y - x y or null null x y`_ | Pushes two nulls under the second stack entry from the top, but only if the topmost _Integer_ `y` is non-zero. Equivalent to [`NULLROTRIF`](#instr-nullrotrif) [`NULLROTRIF`](#instr-nullrotrif). | `26` |
-| **`6FA7`** | `NULLROTRIFNOT2` | _`x y - x y or null null x y`_ | Pushes two nulls under the second stack entry from the top, but only if the topmost _Integer_ `y` is zero. Equivalent to [`NULLROTRIFNOT`](#instr-nullrotrifnot) [`NULLROTRIFNOT`](#instr-nullrotrifnot). | `26` |
-| **`6FBij`** | `[i] [j] INDEX2` | _`t - x`_ | Recovers `x=(t_{i+1})_{j+1}` for `0 <= i,j <= 3`. Equivalent to [`[i] INDEX`](#instr-index) [`[j] INDEX`](#instr-index). | `26` |
-| **`6FB4`** | `CADR` | _`t - x`_ | Recovers `x=(t_2)_1`. | `26` |
-| **`6FB5`** | `CDDR` | _`t - x`_ | Recovers `x=(t_2)_2`. | `26` |
-| **`6FE_ijk`** | `[i] [j] [k] INDEX3` | _`t - x`_ | Recovers `x=t_{i+1}_{j+1}_{k+1}`. `0 <= i,j,k <= 3` Equivalent to [`[i] [j] INDEX2`](#instr-index2) [`[k] INDEX`](#instr-index). | `26` |
-| **`6FD4`** | `CADDR` | _`t - x`_ | Recovers `x=t_2_2_1`. | `26` |
-| **`6FD5`** | `CDDDR` | _`t - x`_ | Recovers `x=t_2_2_2`. | `26` |
-
-## 4 Constant or literal primitives
-### 4.1 Integer and boolean constants
-| xxxxxxx Opcode | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description | xxxx Gas |
-|:-|:-|:-|:-|:-|
-| **`7i`** | `[x] PUSHINT` `[x] INT` | _`- x`_ | Pushes integer `x` into the stack. `-5 <= x <= 10`. Here `i` equals four lower-order bits of `x` (`i=x mod 16`). | `18` |
-| **`70`** | `ZERO` `FALSE` | _`- 0`_ | | `18` |
-| **`71`** | `ONE` | _`- 1`_ | | `18` |
-| **`72`** | `TWO` | _`- 2`_ | | `18` |
-| **`7A`** | `TEN` | _`- 10`_ | | `18` |
-| **`7F`** | `TRUE` | _`- -1`_ | | `18` |
-| **`80xx`** | `[xx] PUSHINT` `[xx] INT` | _`- xx`_ | Pushes integer `xx`. `-128 <= xx <= 127`. | `26` |
-| **`81xxxx`** | `[xxxx] PUSHINT` `[xxxx] INT` | _`- xxxx`_ | Pushes integer `xxxx`. `-2^15 <= xx < 2^15`. | `34` |
-| **`82lxxx`** | `[xxx] PUSHINT` `[xxx] INT` | _`- xxx`_ | Pushes integer `xxx`. _Details:_ 5-bit `0 <= l <= 30` determines the length `n=8l+19` of signed big-endian integer `xxx`. The total length of this instruction is `l+4` bytes or `n+13=8l+32` bits. | `23` |
-| **`83xx`** | `[xx+1] PUSHPOW2` | _`- 2^(xx+1)`_ | (Quietly) pushes `2^(xx+1)` for `0 <= xx <= 255`. `2^256` is a `NaN`. | `26` |
-| **`83FF`** | `PUSHNAN` | _`- NaN`_ | Pushes a `NaN`. | `26` |
-| **`84xx`** | `[xx+1] PUSHPOW2DEC` | _`- 2^(xx+1)-1`_ | Pushes `2^(xx+1)-1` for `0 <= xx <= 255`. | `26` |
-| **`85xx`** | `[xx+1] PUSHNEGPOW2` | _`- -2^(xx+1)`_ | Pushes `-2^(xx+1)` for `0 <= xx <= 255`. | `26` |
-### 4.2 Constant slices, continuations, cells, and references
-| xxxxxxx Opcode | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description | xxxx Gas |
-|:-|:-|:-|:-|:-|
-| **`88`** | `[ref] PUSHREF` | _`- c`_ | Pushes the reference `ref` into the stack. _Details:_ Pushes the first reference of `cc.code` into the stack as a _Cell_ (and removes this reference from the current continuation). | `18` |
-| **`89`** | `[ref] PUSHREFSLICE` | _`- s`_ | Similar to [`PUSHREF`](#instr-pushref), but converts the cell into a _Slice_. | `118/43` |
-| **`8A`** | `[ref] PUSHREFCONT` | _`- cont`_ | Similar to [`PUSHREFSLICE`](#instr-pushrefslice), but makes a simple ordinary _Continuation_ out of the cell. | `118/43` |
-| **`8Bxsss`** | `[slice] PUSHSLICE` `[slice] SLICE` | _`- s`_ | Pushes the slice `slice` into the stack. _Details:_ Pushes the (prefix) subslice of `cc.code` consisting of its first `8x+4` bits and no references (i.e., essentially a bitstring), where `0 <= x <= 15`. A completion tag is assumed, meaning that all trailing zeroes and the last binary one (if present) are removed from this bitstring. If the original bitstring consists only of zeroes, an empty slice will be pushed. | `22` |
-| **`8Crxxssss`** | `[slice] PUSHSLICE` `[slice] SLICE` | _`- s`_ | Pushes the slice `slice` into the stack. _Details:_ Pushes the (prefix) subslice of `cc.code` consisting of its first `1 <= r+1 <= 4` references and up to first `8xx+1` bits of data, with `0 <= xx <= 31`. A completion tag is also assumed. | `25` |
-| **`8Drxxsssss`** | `[slice] PUSHSLICE` `[slice] SLICE` | _`- s`_ | Pushes the slice `slice` into the stack. _Details:_ Pushes the subslice of `cc.code` consisting of `0 <= r <= 4` references and up to `8xx+6` bits of data, with `0 <= xx <= 127`. A completion tag is assumed. | `28` |
-| | `x{} PUSHSLICE` `x{ABCD1234} PUSHSLICE` `b{01101} PUSHSLICE` | _`- s`_ | Examples of [`PUSHSLICE`](#instr-pushslice). `x{}` is an empty slice. `x{...}` is a hexadecimal literal. `b{...}` is a binary literal. More on slice literals [here](https://github.com/Piterden/TON-docs/blob/master/Fift.%20A%20Brief%20Introduction.md#user-content-51-slice-literals). Note that the assembler can replace [`PUSHSLICE`](#instr-pushslice) with [`PUSHREFSLICE`](#instr-pushrefslice) in certain situations (e.g. if there’s not enough space in the current continuation). | |
-| | ` PUSHREF` ` PUSHREFSLICE` | _`- c/s`_ | Examples of [`PUSHREF`](#instr-pushref) and [`PUSHREFSLICE`](#instr-pushrefslice). More on building cells in fift [here](https://github.com/Piterden/TON-docs/blob/master/Fift.%20A%20Brief%20Introduction.md#user-content-52-builder-primitives). | |
-| **`8F_rxxcccc`** | `[builder] PUSHCONT` `[builder] CONT` | _`- c`_ | Pushes a continuation made from `builder`. _Details:_ Pushes the simple ordinary continuation `cccc` made from the first `0 <= r <= 3` references and the first `0 <= xx <= 127` bytes of `cc.code`. | `26` |
-| **`9xccc`** | `[builder] PUSHCONT` `[builder] CONT` | _`- c`_ | Pushes a continuation made from `builder`. _Details:_ Pushes an `x`-byte continuation for `0 <= x <= 15`. | `18` |
-| | `<{ code }> PUSHCONT` `<{ code }> CONT` `CONT:<{ code }>` | _`- c`_ | Pushes a continuation with code `code`. Note that the assembler can replace [`PUSHCONT`](#instr-pushcont) with [`PUSHREFCONT`](#instr-pushrefcont) in certain situations (e.g. if there’s not enough space in the current continuation). | |
-
-## 5 Arithmetic primitives
-### 5.1 Addition, subtraction, multiplication
-| xxxxxxx Opcode | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description | xxxx Gas |
-|:-|:-|:-|:-|:-|
-| **`A0`** | `ADD` | _`x y - x+y`_ | | `18` |
-| **`A1`** | `SUB` | _`x y - x-y`_ | | `18` |
-| **`A2`** | `SUBR` | _`x y - y-x`_ | Equivalent to [`SWAP`](#instr-swap) [`SUB`](#instr-sub). | `18` |
-| **`A3`** | `NEGATE` | _`x - -x`_ | Equivalent to [`-1 MULCONST`](#instr-mulconst) or to [`ZERO SUBR`](#instr-subr). Notice that it triggers an integer overflow exception if `x=-2^256`. | `18` |
-| **`A4`** | `INC` | _`x - x+1`_ | Equivalent to [`1 ADDCONST`](#instr-addconst). | `18` |
-| **`A5`** | `DEC` | _`x - x-1`_ | Equivalent to [`-1 ADDCONST`](#instr-addconst). | `18` |
-| **`A6cc`** | `[cc] ADDCONST` `[cc] ADDINT` `[-cc] SUBCONST` `[-cc] SUBINT` | _`x - x+cc`_ | `-128 <= cc <= 127`. | `26` |
-| **`A7cc`** | `[cc] MULCONST` `[cc] MULINT` | _`x - x*cc`_ | `-128 <= cc <= 127`. | `26` |
-| **`A8`** | `MUL` | _`x y - x*y`_ | | `18` |
-### 5.2 Division
-| xxxxxxx Opcode | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description | xxxx Gas |
-|:-|:-|:-|:-|:-|
-| **`A9mscdf`** | | | This is the general encoding of division, with an optional pre-multiplication and an optional replacement of the division or multiplication by a shift. Variable fields are as follows: `0 <= m <= 1` - Indicates whether there is pre-multiplication ([`MULDIV`](#instr-muldiv) and its variants), possibly replaced by a left shift. `0 <= s <= 2` - Indicates whether either the multiplication or the division have been replaced by shifts: `s=0` - no replacement, `s=1` - division replaced by a right shift, `s=2` - multiplication replaced by a left shift (possible only for `m=1`). `0 <= c <= 1` - Indicates whether there is a constant one-byte argument `tt` for the shift operator (if `s!=0`). For `s=0`, `c=0`. If `c=1`, then `0 <= tt <= 255`, and the shift is performed by `tt+1` bits. If `s!=0` and `c=0`, then the shift amount is provided to the instruction as a top-of-stack _Integer_ in range `0...256`. `1 <= d <= 3` - Indicates which results of division are required: `1` - only the quotient, `2` - only the remainder, `3` - both. `0 <= f <= 2` - Rounding mode: `0` - floor, `1` - nearest integer, `2` - ceiling. All instructions below are variants of this. | `26` |
-| **`A904`** | `DIV` | _`x y - q`_ | `q=floor(x/y)`, `r=x-y*q` | `26` |
-| **`A905`** | `DIVR` | _`x y - q’`_ | `q’=round(x/y)`, `r’=x-y*q’` | `26` |
-| **`A906`** | `DIVC` | _`x y - q''`_ | `q’’=ceil(x/y)`, `r’’=x-y*q’’` | `26` |
-| **`A908`** | `MOD` | _`x y - r`_ | | `26` |
-| **`A90C`** | `DIVMOD` | _`x y - q r`_ | | `26` |
-| **`A90D`** | `DIVMODR` | _`x y - q' r'`_ | | `26` |
-| **`A90E`** | `DIVMODC` | _`x y - q'' r''`_ | | `26` |
-| **`A925`** | `RSHIFTR` | _`x y - round(x/2^y)`_ | | `26` |
-| **`A926`** | `RSHIFTC` | _`x y - ceil(x/2^y)`_ | | `34` |
-| **`A935tt`** | `[tt+1] RSHIFTR#` | _`x y - round(x/2^(tt+1))`_ | | `34` |
-| **`A936tt`** | `[tt+1] RSHIFTC#` | _`x y - ceil(x/2^(tt+1))`_ | | `34` |
-| **`A938tt`** | `[tt+1] MODPOW2#` | _`x - x mod 2^(tt+1)`_ | | `34` |
-| **`A98`** | `MULDIV` | _`x y z - q`_ | `q=floor(x*y/z)` | `26` |
-| **`A985`** | `MULDIVR` | _`x y z - q'`_ | `q'=round(x*y/z)` | `26` |
-| **`A98C`** | `MULDIVMOD` | _`x y z - q r`_ | `q=floor(x*y/z)`, `r=x*y-z*q` | `26` |
-| **`A9A4`** | `MULRSHIFT` | _`x y z - floor(x*y/2^z)`_ | `0 <= z <= 256` | `26` |
-| **`A9A5`** | `MULRSHIFTR` | _`x y z - round(x*y/2^z)`_ | `0 <= z <= 256` | `26` |
-| **`A9A6`** | `MULRSHIFTC` | _`x y z - ceil(x*y/2^z)`_ | `0 <= z <= 256` | `34` |
-| **`A9B4tt`** | `[tt+1] MULRSHIFT#` | _`x y - floor(x*y/2^(tt+1))`_ | | `34` |
-| **`A9B5tt`** | `[tt+1] MULRSHIFTR#` | _`x y - round(x*y/2^(tt+1))`_ | | `34` |
-| **`A9B6tt`** | `[tt+1] MULRSHIFTC#` | _`x y - ceil(x*y/2^(tt+1))`_ | | `26` |
-| **`A9C4`** | `LSHIFTDIV` | _`x y z - floor(2^z*x/y)`_ | `0 <= z <= 256` | `26` |
-| **`A9C5`** | `LSHIFTDIVR` | _`x y z - round(2^z*x/y)`_ | `0 <= z <= 256` | `26` |
-| **`A9C6`** | `LSHIFTDIVC` | _`x y z - ceil(2^z*x/y)`_ | `0 <= z <= 256` | `34` |
-| **`A9D4tt`** | `[tt+1] LSHIFT#DIV` | _`x y - floor(2^(tt+1)*x/y)`_ | | `34` |
-| **`A9D5tt`** | `[tt+1] LSHIFT#DIVR` | _`x y - round(2^(tt+1)*x/y)`_ | | `34` |
-| **`A9D6tt`** | `[tt+1] LSHIFT#DIVC` | _`x y - ceil(2^(tt+1)*x/y)`_ | | `26` |
-### 5.3 Shifts, logical operations
-| xxxxxxx Opcode | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description | xxxx Gas |
-|:-|:-|:-|:-|:-|
-| **`AAcc`** | `[cc+1] LSHIFT#` | _`x - x*2^(cc+1)`_ | `0 <= cc <= 255` | `26` |
-| **`ABcc`** | `[cc+1] RSHIFT#` | _`x - floor(x/2^(cc+1))`_ | `0 <= cc <= 255` | `18` |
-| **`AC`** | `LSHIFT` | _`x y - x*2^y`_ | `0 <= y <= 1023` | `18` |
-| **`AD`** | `RSHIFT` | _`x y - floor(x/2^y)`_ | `0 <= y <= 1023` | `18` |
-| **`AE`** | `POW2` | _`y - 2^y`_ | `0 <= y <= 1023` Equivalent to [`ONE`](#instr-one) [`SWAP`](#instr-swap) [`LSHIFT`](#instr-lshift-var). | `18` |
-| **`B0`** | `AND` | _`x y - x&y`_ | Bitwise and of two signed integers `x` and `y`, sign-extended to infinity. | `18` |
-| **`B1`** | `OR` | _`x y - x\|y`_ | Bitwise or of two integers. | `18` |
-| **`B2`** | `XOR` | _`x y - x xor y`_ | Bitwise xor of two integers. | `18` |
-| **`B3`** | `NOT` | _`x - ~x`_ | Bitwise not of an integer. | `26` |
-| **`B4cc`** | `[cc+1] FITS` | _`x - x`_ | Checks whether `x` is a `cc+1`-bit signed integer for `0 <= cc <= 255` (i.e., whether `-2^cc <= x < 2^cc`). If not, either triggers an integer overflow exception, or replaces `x` with a `NaN` (quiet version). | `26/76` |
-| **`B400`** | `CHKBOOL` | _`x - x`_ | Checks whether `x` is a “boolean value'' (i.e., either 0 or -1). | `26/76` |
-| **`B5cc`** | `[cc+1] UFITS` | _`x - x`_ | Checks whether `x` is a `cc+1`-bit unsigned integer for `0 <= cc <= 255` (i.e., whether `0 <= x < 2^(cc+1)`). | `26/76` |
-| **`B500`** | `CHKBIT` | _`x - x`_ | Checks whether `x` is a binary digit (i.e., zero or one). | `26/76` |
-| **`B600`** | `FITSX` | _`x c - x`_ | Checks whether `x` is a `c`-bit signed integer for `0 <= c <= 1023`. | `26/76` |
-| **`B601`** | `UFITSX` | _`x c - x`_ | Checks whether `x` is a `c`-bit unsigned integer for `0 <= c <= 1023`. | `26/76` |
-| **`B602`** | `BITSIZE` | _`x - c`_ | Computes smallest `c >= 0` such that `x` fits into a `c`-bit signed integer (`-2^(c-1) <= c < 2^(c-1)`). | `26` |
-| **`B603`** | `UBITSIZE` | _`x - c`_ | Computes smallest `c >= 0` such that `x` fits into a `c`-bit unsigned integer (`0 <= x < 2^c`), or throws a range check exception. | `26` |
-| **`B608`** | `MIN` | _`x y - x or y`_ | Computes the minimum of two integers `x` and `y`. | `26` |
-| **`B609`** | `MAX` | _`x y - x or y`_ | Computes the maximum of two integers `x` and `y`. | `26` |
-| **`B60A`** | `MINMAX` `INTSORT2` | _`x y - x y or y x`_ | Sorts two integers. Quiet version of this operation returns two `NaN`s if any of the arguments are `NaN`s. | `26` |
-| **`B60B`** | `ABS` | _`x - \|x\|`_ | Computes the absolute value of an integer `x`. | `26` |
-### 5.4 Quiet arithmetic primitives
-Quiet operations return `NaN` instead of throwing exceptions if one of their arguments is a `NaN` or in the case of an integer overflow.
-Quiet operations have a prefix `Q` as shown below. Another way to make an operation quiet is to add `QUIET` before it (i.e. one can write [`QUIET ADD`](#instr-add) instead of [`QADD`](#instr-qadd)).
-Quiet versions of integer comparison primitives are also available ([`QUIET SGN`](#instr-sgn), [`QUIET LESS`](#instr-less) etc).
-
-| xxxxxxx Opcode | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description | xxxx Gas |
-|:-|:-|:-|:-|:-|
-| **`B7A0`** | `QADD` | _`x y - x+y`_ | | `26` |
-| **`B7A1`** | `QSUB` | _`x y - x-y`_ | | `26` |
-| **`B7A2`** | `QSUBR` | _`x y - y-x`_ | | `26` |
-| **`B7A3`** | `QNEGATE` | _`x - -x`_ | | `26` |
-| **`B7A4`** | `QINC` | _`x - x+1`_ | | `26` |
-| **`B7A5`** | `QDEC` | _`x - x-1`_ | | `26` |
-| **`B7A8`** | `QMUL` | _`x y - x*y`_ | | `26` |
-| **`B7A904`** | `QDIV` | _`x y - q`_ | Division returns `NaN` if `y=0`. | `34` |
-| **`B7A905`** | `QDIVR` | _`x y - q’`_ | | `34` |
-| **`B7A906`** | `QDIVC` | _`x y - q''`_ | | `34` |
-| **`B7A908`** | `QMOD` | _`x y - r`_ | | `34` |
-| **`B7A90C`** | `QDIVMOD` | _`x y - q r`_ | | `34` |
-| **`B7A90D`** | `QDIVMODR` | _`x y - q' r'`_ | | `34` |
-| **`B7A90E`** | `QDIVMODC` | _`x y - q'' r''`_ | | `34` |
-| **`B7A985`** | `QMULDIVR` | _`x y z - q'`_ | | `34` |
-| **`B7A98C`** | `QMULDIVMOD` | _`x y z - q r`_ | | `34` |
-| **`B7AC`** | `QLSHIFT` | _`x y - x*2^y`_ | | `26` |
-| **`B7AD`** | `QRSHIFT` | _`x y - floor(x/2^y)`_ | | `26` |
-| **`B7AE`** | `QPOW2` | _`y - 2^y`_ | | `26` |
-| **`B7B0`** | `QAND` | _`x y - x&y`_ | | `26` |
-| **`B7B1`** | `QOR` | _`x y - x\|y`_ | | `26` |
-| **`B7B2`** | `QXOR` | _`x y - x xor y`_ | | `26` |
-| **`B7B3`** | `QNOT` | _`x - ~x`_ | | `26` |
-| **`B7B4cc`** | `[cc+1] QFITS` | _`x - x`_ | Replaces `x` with a `NaN` if x is not a `cc+1`-bit signed integer, leaves it intact otherwise. | `34` |
-| **`B7B5cc`** | `[cc+1] QUFITS` | _`x - x`_ | Replaces `x` with a `NaN` if x is not a `cc+1`-bit unsigned integer, leaves it intact otherwise. | `34` |
-| **`B7B600`** | `QFITSX` | _`x c - x`_ | Replaces `x` with a `NaN` if x is not a c-bit signed integer, leaves it intact otherwise. | `34` |
-| **`B7B601`** | `QUFITSX` | _`x c - x`_ | Replaces `x` with a `NaN` if x is not a c-bit unsigned integer, leaves it intact otherwise. | `34` |
-
-## 6 Comparison primitives
-### 6.1 Integer comparison
-| xxxxxxx Opcode | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description | xxxx Gas |
-|:-|:-|:-|:-|:-|
-| **`B8`** | `SGN` | _`x - sgn(x)`_ | Computes the sign of an integer `x`: `-1` if `x<0`, `0` if `x=0`, `1` if `x>0`. | `18` |
-| **`B9`** | `LESS` | _`x y - xy`_ | | `18` |
-| **`BD`** | `NEQ` | _`x y - x!=y`_ | Equivalent to [`EQUAL`](#instr-equal) [`NOT`](#instr-not). | `18` |
-| **`BE`** | `GEQ` | _`x y - x>=y`_ | Equivalent to [`LESS`](#instr-less) [`NOT`](#instr-not). | `18` |
-| **`BF`** | `CMP` | _`x y - sgn(x-y)`_ | Computes the sign of `x-y`: `-1` if `xy`. No integer overflow can occur here unless `x` or `y` is a `NaN`. | `18` |
-| **`C0yy`** | `[yy] EQINT` | _`x - x=yy`_ | Returns `-1` if `x=yy`, `0` otherwise. `-2^7 <= yy < 2^7`. | `26` |
-| **`C000`** | `ISZERO` | _`x - x=0`_ | Checks whether an integer is zero. Corresponds to Forth's `0=`. | `26` |
-| **`C1yy`** | `[yy] LESSINT` `[yy-1] LEQINT` | _`x - x `-2^7 <= yy < 2^7`. | `26` |
-| **`C100`** | `ISNEG` | _`x - x<0`_ | Checks whether an integer is negative. Corresponds to Forth's `0<`. | `26` |
-| **`C101`** | `ISNPOS` | _`x - x<=0`_ | Checks whether an integer is non-positive. | `26` |
-| **`C2yy`** | `[yy] GTINT` `[yy+1] GEQINT` | _`x - x>yy`_ | Returns `-1` if `x>yy`, `0` otherwise. `-2^7 <= yy < 2^7`. | `26` |
-| **`C200`** | `ISPOS` | _`x - x>0`_ | Checks whether an integer is positive. Corresponds to Forth's `0>`. | `26` |
-| **`C2FF`** | `ISNNEG` | _`x - x >=0`_ | Checks whether an integer is non-negative. | `26` |
-| **`C3yy`** | `[yy] NEQINT` | _`x - x!=yy`_ | Returns `-1` if `x!=yy`, `0` otherwise. `-2^7 <= yy < 2^7`. | `26` |
-| **`C4`** | `ISNAN` | _`x - x=NaN`_ | Checks whether `x` is a `NaN`. | `18` |
-| **`C5`** | `CHKNAN` | _`x - x`_ | Throws an arithmetic overflow exception if `x` is a `NaN`. | `18/68` |
-### 6.2 Other comparison
-Most of these "other comparison" primitives actually compare the data portions of _Slices_ as bitstrings (ignoring references if not stated otherwise).
-
-| xxxxxxx Opcode | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description | xxxx Gas |
-|:-|:-|:-|:-|:-|
-| **`C700`** | `SEMPTY` | _`s - ?`_ | Checks whether a _Slice_ `s` is empty (i.e., contains no bits of data and no cell references). | `26` |
-| **`C701`** | `SDEMPTY` | _`s - ?`_ | Checks whether _Slice_ `s` has no bits of data. | `26` |
-| **`C702`** | `SREMPTY` | _`s - ?`_ | Checks whether _Slice_ `s` has no references. | `26` |
-| **`C703`** | `SDFIRST` | _`s - ?`_ | Checks whether the first bit of _Slice_ `s` is a one. | `26` |
-| **`C704`** | `SDLEXCMP` | _`s s' - x`_ | Compares the data of `s` lexicographically with the data of `s'`, returning `-1`, 0, or 1 depending on the result. | `26` |
-| **`C705`** | `SDEQ` | _`s s' - ?`_ | Checks whether the data parts of `s` and `s'` coincide, equivalent to [`SDLEXCMP`](#instr-sdlexcmp) [`ISZERO`](#instr-iszero). | `26` |
-| **`C708`** | `SDPFX` | _`s s' - ?`_ | Checks whether `s` is a prefix of `s'`. | `26` |
-| **`C709`** | `SDPFXREV` | _`s s' - ?`_ | Checks whether `s'` is a prefix of `s`, equivalent to [`SWAP`](#instr-swap) [`SDPFX`](#instr-sdpfx). | `26` |
-| **`C70A`** | `SDPPFX` | _`s s' - ?`_ | Checks whether `s` is a proper prefix of `s'` (i.e., a prefix distinct from `s'`). | `26` |
-| **`C70B`** | `SDPPFXREV` | _`s s' - ?`_ | Checks whether `s'` is a proper prefix of `s`. | `26` |
-| **`C70C`** | `SDSFX` | _`s s' - ?`_ | Checks whether `s` is a suffix of `s'`. | `26` |
-| **`C70D`** | `SDSFXREV` | _`s s' - ?`_ | Checks whether `s'` is a suffix of `s`. | `26` |
-| **`C70E`** | `SDPSFX` | _`s s' - ?`_ | Checks whether `s` is a proper suffix of `s'`. | `26` |
-| **`C70F`** | `SDPSFXREV` | _`s s' - ?`_ | Checks whether `s'` is a proper suffix of `s`. | `26` |
-| **`C710`** | `SDCNTLEAD0` | _`s - n`_ | Returns the number of leading zeroes in `s`. | `26` |
-| **`C711`** | `SDCNTLEAD1` | _`s - n`_ | Returns the number of leading ones in `s`. | `26` |
-| **`C712`** | `SDCNTTRAIL0` | _`s - n`_ | Returns the number of trailing zeroes in `s`. | `26` |
-| **`C713`** | `SDCNTTRAIL1` | _`s - n`_ | Returns the number of trailing ones in `s`. | `26` |
-
-## 7 Cell primitives
-### 7.1 Cell serialization primitives
-| xxxxxxx Opcode | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description | xxxx Gas |
-|:-|:-|:-|:-|:-|
-| **`C8`** | `NEWC` | _`- b`_ | Creates a new empty _Builder_. | `18` |
-| **`C9`** | `ENDC` | _`b - c`_ | Converts a _Builder_ into an ordinary _Cell_. | `518` |
-| **`CAcc`** | `[cc+1] STI` | _`x b - b'`_ | Stores a signed `cc+1`-bit integer `x` into _Builder_ `b` for `0 <= cc <= 255`, throws a range check exception if `x` does not fit into `cc+1` bits. | `26` |
-| **`CBcc`** | `[cc+1] STU` | _`x b - b'`_ | Stores an unsigned `cc+1`-bit integer `x` into _Builder_ `b`. In all other respects it is similar to [`STI`](#instr-sti). | `26` |
-| **`CC`** | `STREF` | _`c b - b'`_ | Stores a reference to _Cell_ `c` into _Builder_ `b`. | `18` |
-| **`CD`** | `STBREFR` `ENDCST` | _`b b'' - b`_ | Equivalent to [`ENDC`](#instr-endc) [`SWAP`](#instr-swap) [`STREF`](#instr-stref). | `518` |
-| **`CE`** | `STSLICE` | _`s b - b'`_ | Stores _Slice_ `s` into _Builder_ `b`. | `18` |
-| **`CF00`** | `STIX` | _`x b l - b'`_ | Stores a signed `l`-bit integer `x` into `b` for `0 <= l <= 257`. | `26` |
-| **`CF01`** | `STUX` | _`x b l - b'`_ | Stores an unsigned `l`-bit integer `x` into `b` for `0 <= l <= 256`. | `26` |
-| **`CF02`** | `STIXR` | _`b x l - b'`_ | Similar to [`STIX`](#instr-stix), but with arguments in a different order. | `26` |
-| **`CF03`** | `STUXR` | _`b x l - b'`_ | Similar to [`STUX`](#instr-stux), but with arguments in a different order. | `26` |
-| **`CF04`** | `STIXQ` | _`x b l - x b f or b' 0`_ | A quiet version of [`STIX`](#instr-stix). If there is no space in `b`, sets `b'=b` and `f=-1`. If `x` does not fit into `l` bits, sets `b'=b` and `f=1`. If the operation succeeds, `b'` is the new _Builder_ and `f=0`. However, `0 <= l <= 257`, with a range check exception if this is not so. | `26` |
-| **`CF05`** | `STUXQ` | _`x b l - x b f or b' 0`_ | A quiet version of [`STUX`](#instr-stux). | `26` |
-| **`CF06`** | `STIXRQ` | _`b x l - b x f or b' 0`_ | A quiet version of [`STIXR`](#instr-stixr). | `26` |
-| **`CF07`** | `STUXRQ` | _`b x l - b x f or b' 0`_ | A quiet version of [`STUXR`](#instr-stuxr). | `26` |
-| **`CF08cc`** | `[cc+1] STI_l` | _`x b - b'`_ | A longer version of [`[cc+1] STI`](#instr-sti). | `34` |
-| **`CF09cc`** | `[cc+1] STU_l` | _`x b - b'`_ | A longer version of [`[cc+1] STU`](#instr-stu). | `34` |
-| **`CF0Acc`** | `[cc+1] STIR` | _`b x - b'`_ | Equivalent to [`SWAP`](#instr-swap) [`[cc+1] STI`](#instr-sti). | `34` |
-| **`CF0Bcc`** | `[cc+1] STUR` | _`b x - b'`_ | Equivalent to [`SWAP`](#instr-swap) [`[cc+1] STU`](#instr-stu). | `34` |
-| **`CF0Ccc`** | `[cc+1] STIQ` | _`x b - x b f or b' 0`_ | A quiet version of [`STI`](#instr-sti). | `34` |
-| **`CF0Dcc`** | `[cc+1] STUQ` | _`x b - x b f or b' 0`_ | A quiet version of [`STU`](#instr-stu). | `34` |
-| **`CF0Ecc`** | `[cc+1] STIRQ` | _`b x - b x f or b' 0`_ | A quiet version of [`STIR`](#instr-stir). | `34` |
-| **`CF0Fcc`** | `[cc+1] STURQ` | _`b x - b x f or b' 0`_ | A quiet version of [`STUR`](#instr-stur). | `34` |
-| **`CF10`** | `STREF_l` | _`c b - b'`_ | A longer version of [`STREF`](#instr-stref). | `26` |
-| **`CF11`** | `STBREF` | _`b' b - b''`_ | Equivalent to [`SWAP`](#instr-swap) [`STBREFR`](#instr-stbrefr). | `526` |
-| **`CF12`** | `STSLICE_l` | _`s b - b'`_ | A longer version of [`STSLICE`](#instr-stslice). | `26` |
-| **`CF13`** | `STB` | _`b' b - b''`_ | Appends all data from _Builder_ `b'` to _Builder_ `b`. | `26` |
-| **`CF14`** | `STREFR` | _`b c - b'`_ | Equivalent to [`SWAP`](#instr-swap) [`STREF`](#instr-stref). | `26` |
-| **`CF15`** | `STBREFR_l` | _`b b' - b''`_ | A longer encoding of [`STBREFR`](#instr-stbrefr). | `526` |
-| **`CF16`** | `STSLICER` | _`b s - b'`_ | Equivalent to [`SWAP`](#instr-swap) [`STSLICE`](#instr-stslice). | `26` |
-| **`CF17`** | `STBR` `BCONCAT` | _`b b' - b''`_ | Concatenates two builders. Equivalent to [`SWAP`](#instr-swap) [`STB`](#instr-stb). | `26` |
-| **`CF18`** | `STREFQ` | _`c b - c b -1 or b' 0`_ | Quiet version of [`STREF`](#instr-stref). | `26` |
-| **`CF19`** | `STBREFQ` | _`b' b - b' b -1 or b'' 0`_ | Quiet version of [`STBREF`](#instr-stbref). | `526` |
-| **`CF1A`** | `STSLICEQ` | _`s b - s b -1 or b' 0`_ | Quiet version of [`STSLICE`](#instr-stslice). | `26` |
-| **`CF1B`** | `STBQ` | _`b' b - b' b -1 or b'' 0`_ | Quiet version of [`STB`](#instr-stb). | `26` |
-| **`CF1C`** | `STREFRQ` | _`b c - b c -1 or b' 0`_ | Quiet version of [`STREFR`](#instr-strefr). | `26` |
-| **`CF1D`** | `STBREFRQ` | _`b b' - b b' -1 or b'' 0`_ | Quiet version of [`STBREFR`](#instr-stbrefr). | `526` |
-| **`CF1E`** | `STSLICERQ` | _`b s - b s -1 or b'' 0`_ | Quiet version of [`STSLICER`](#instr-stslicer). | `26` |
-| **`CF1F`** | `STBRQ` `BCONCATQ` | _`b b' - b b' -1 or b'' 0`_ | Quiet version of [`STBR`](#instr-stbr). | `26` |
-| **`CF20`** | `[ref] STREFCONST` | _`b - b’`_ | Equivalent to [`PUSHREF`](#instr-pushref) [`STREFR`](#instr-strefr). | `26` |
-| **`CF21`** | `[ref] [ref] STREF2CONST` | _`b - b’`_ | Equivalent to [`STREFCONST`](#instr-strefconst) [`STREFCONST`](#instr-strefconst). | `26` |
-| **`CF23`** | | _`b x - c`_ | If `x!=0`, creates a _special_ or _exotic_ cell from _Builder_ `b`. The type of the exotic cell must be stored in the first 8 bits of `b`. If `x=0`, it is equivalent to [`ENDC`](#instr-endc). Otherwise some validity checks on the data and references of `b` are performed before creating the exotic cell. | `526` |
-| **`CF28`** | `STILE4` | _`x b - b'`_ | Stores a little-endian signed 32-bit integer. | `26` |
-| **`CF29`** | `STULE4` | _`x b - b'`_ | Stores a little-endian unsigned 32-bit integer. | `26` |
-| **`CF2A`** | `STILE8` | _`x b - b'`_ | Stores a little-endian signed 64-bit integer. | `26` |
-| **`CF2B`** | `STULE8` | _`x b - b'`_ | Stores a little-endian unsigned 64-bit integer. | `26` |
-| **`CF30`** | `BDEPTH` | _`b - x`_ | Returns the depth of _Builder_ `b`. If no cell references are stored in `b`, then `x=0`; otherwise `x` is one plus the maximum of depths of cells referred to from `b`. | `26` |
-| **`CF31`** | `BBITS` | _`b - x`_ | Returns the number of data bits already stored in _Builder_ `b`. | `26` |
-| **`CF32`** | `BREFS` | _`b - y`_ | Returns the number of cell references already stored in `b`. | `26` |
-| **`CF33`** | `BBITREFS` | _`b - x y`_ | Returns the numbers of both data bits and cell references in `b`. | `26` |
-| **`CF35`** | `BREMBITS` | _`b - x'`_ | Returns the number of data bits that can still be stored in `b`. | `26` |
-| **`CF36`** | `BREMREFS` | _`b - y'`_ | Returns the number of references that can still be stored in `b`. | `26` |
-| **`CF37`** | `BREMBITREFS` | _`b - x' y'`_ | Returns the numbers of both data bits and references that can still be stored in `b`. | `26` |
-| **`CF38cc`** | `[cc+1] BCHKBITS#` | _`b -`_ | Checks whether `cc+1` bits can be stored into `b`, where `0 <= cc <= 255`. | `34/84` |
-| **`CF39`** | `BCHKBITS` | _`b x - `_ | Checks whether `x` bits can be stored into `b`, `0 <= x <= 1023`. If there is no space for `x` more bits in `b`, or if `x` is not within the range `0...1023`, throws an exception. | `26/76` |
-| **`CF3A`** | `BCHKREFS` | _`b y - `_ | Checks whether `y` references can be stored into `b`, `0 <= y <= 7`. | `26/76` |
-| **`CF3B`** | `BCHKBITREFS` | _`b x y - `_ | Checks whether `x` bits and `y` references can be stored into `b`, `0 <= x <= 1023`, `0 <= y <= 7`. | `26/76` |
-| **`CF3Ccc`** | `[cc+1] BCHKBITSQ#` | _`b - ?`_ | Checks whether `cc+1` bits can be stored into `b`, where `0 <= cc <= 255`. | `34` |
-| **`CF3D`** | `BCHKBITSQ` | _`b x - ?`_ | Checks whether `x` bits can be stored into `b`, `0 <= x <= 1023`. | `26` |
-| **`CF3E`** | `BCHKREFSQ` | _`b y - ?`_ | Checks whether `y` references can be stored into `b`, `0 <= y <= 7`. | `26` |
-| **`CF3F`** | `BCHKBITREFSQ` | _`b x y - ?`_ | Checks whether `x` bits and `y` references can be stored into `b`, `0 <= x <= 1023`, `0 <= y <= 7`. | `26` |
-| **`CF40`** | `STZEROES` | _`b n - b'`_ | Stores `n` binary zeroes into _Builder_ `b`. | `26` |
-| **`CF41`** | `STONES` | _`b n - b'`_ | Stores `n` binary ones into _Builder_ `b`. | `26` |
-| **`CF42`** | `STSAME` | _`b n x - b'`_ | Stores `n` binary `x`es (`0 <= x <= 1`) into _Builder_ `b`. | `26` |
-| **`CFC0_xysss`** | `[slice] STSLICECONST` | _`b - b'`_ | Stores a constant subslice `sss`. _Details:_ `sss` consists of `0 <= x <= 3` references and up to `8y+2` data bits, with `0 <= y <= 7`. Completion bit is assumed. Note that the assembler can replace [`STSLICECONST`](#instr-stsliceconst) with [`PUSHSLICE`](#instr-pushslice) [`STSLICER`](#instr-stslicer) if the slice is too big. | `24` |
-| **`CF81`** | `STZERO` | _`b - b'`_ | Stores one binary zero. | `24` |
-| **`CF83`** | `STONE` | _`b - b'`_ | Stores one binary one. | `24` |
-### 7.2 Cell deserialization primitives
-| xxxxxxx Opcode | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description | xxxx Gas |
-|:-|:-|:-|:-|:-|
-| **`D0`** | `CTOS` | _`c - s`_ | Converts a _Cell_ into a _Slice_. Notice that `c` must be either an ordinary cell, or an exotic cell which is automatically _loaded_ to yield an ordinary cell `c'`, converted into a _Slice_ afterwards. | `118/43` |
-| **`D1`** | `ENDS` | _`s - `_ | Removes a _Slice_ `s` from the stack, and throws an exception if it is not empty. | `18/68` |
-| **`D2cc`** | `[cc+1] LDI` | _`s - x s'`_ | Loads (i.e., parses) a signed `cc+1`-bit integer `x` from _Slice_ `s`, and returns the remainder of `s` as `s'`. | `26` |
-| **`D3cc`** | `[cc+1] LDU` | _`s - x s'`_ | Loads an unsigned `cc+1`-bit integer `x` from _Slice_ `s`. | `26` |
-| **`D4`** | `LDREF` | _`s - c s'`_ | Loads a cell reference `c` from `s`. | `18` |
-| **`D5`** | `LDREFRTOS` | _`s - s' s''`_ | Equivalent to [`LDREF`](#instr-ldref) [`SWAP`](#instr-swap) [`CTOS`](#instr-ctos). | `118/43` |
-| **`D6cc`** | `[cc+1] LDSLICE` | _`s - s'' s'`_ | Cuts the next `cc+1` bits of `s` into a separate _Slice_ `s''`. | `26` |
-| **`D700`** | `LDIX` | _`s l - x s'`_ | Loads a signed `l`-bit (`0 <= l <= 257`) integer `x` from _Slice_ `s`, and returns the remainder of `s` as `s'`. | `26` |
-| **`D701`** | `LDUX` | _`s l - x s'`_ | Loads an unsigned `l`-bit integer `x` from (the first `l` bits of) `s`, with `0 <= l <= 256`. | `26` |
-| **`D702`** | `PLDIX` | _`s l - x`_ | Preloads a signed `l`-bit integer from _Slice_ `s`, for `0 <= l <= 257`. | `26` |
-| **`D703`** | `PLDUX` | _`s l - x`_ | Preloads an unsigned `l`-bit integer from `s`, for `0 <= l <= 256`. | `26` |
-| **`D704`** | `LDIXQ` | _`s l - x s' -1 or s 0`_ | Quiet version of [`LDIX`](#instr-ldix): loads a signed `l`-bit integer from `s` similarly to [`LDIX`](#instr-ldix), but returns a success flag, equal to `-1` on success or to `0` on failure (if `s` does not have `l` bits), instead of throwing a cell underflow exception. | `26` |
-| **`D705`** | `LDUXQ` | _`s l - x s' -1 or s 0`_ | Quiet version of [`LDUX`](#instr-ldux). | `26` |
-| **`D706`** | `PLDIXQ` | _`s l - x -1 or 0`_ | Quiet version of [`PLDIX`](#instr-pldix). | `26` |
-| **`D707`** | `PLDUXQ` | _`s l - x -1 or 0`_ | Quiet version of [`PLDUX`](#instr-pldux). | `26` |
-| **`D708cc`** | `[cc+1] LDI_l` | _`s - x s'`_ | A longer encoding for [`LDI`](#instr-ldi). | `34` |
-| **`D709cc`** | `[cc+1] LDU_l` | _`s - x s'`_ | A longer encoding for [`LDU`](#instr-ldu). | `34` |
-| **`D70Acc`** | `[cc+1] PLDI` | _`s - x`_ | Preloads a signed `cc+1`-bit integer from _Slice_ `s`. | `34` |
-| **`D70Bcc`** | `[cc+1] PLDU` | _`s - x`_ | Preloads an unsigned `cc+1`-bit integer from `s`. | `34` |
-| **`D70Ccc`** | `[cc+1] LDIQ` | _`s - x s' -1 or s 0`_ | A quiet version of [`LDI`](#instr-ldi). | `34` |
-| **`D70Dcc`** | `[cc+1] LDUQ` | _`s - x s' -1 or s 0`_ | A quiet version of [`LDU`](#instr-ldu). | `34` |
-| **`D70Ecc`** | `[cc+1] PLDIQ` | _`s - x -1 or 0`_ | A quiet version of [`PLDI`](#instr-pldi). | `34` |
-| **`D70Fcc`** | `[cc+1] PLDUQ` | _`s - x -1 or 0`_ | A quiet version of [`PLDU`](#instr-pldu). | `34` |
-| **`D714_c`** | `[32(c+1)] PLDUZ` | _`s - s x`_ | Preloads the first `32(c+1)` bits of _Slice_ `s` into an unsigned integer `x`, for `0 <= c <= 7`. If `s` is shorter than necessary, missing bits are assumed to be zero. This operation is intended to be used along with [`IFBITJMP`](#instr-ifbitjmp) and similar instructions. | `26` |
-| **`D718`** | `LDSLICEX` | _`s l - s'' s'`_ | Loads the first `0 <= l <= 1023` bits from _Slice_ `s` into a separate _Slice_ `s''`, returning the remainder of `s` as `s'`. | `26` |
-| **`D719`** | `PLDSLICEX` | _`s l - s''`_ | Returns the first `0 <= l <= 1023` bits of `s` as `s''`. | `26` |
-| **`D71A`** | `LDSLICEXQ` | _`s l - s'' s' -1 or s 0`_ | A quiet version of [`LDSLICEX`](#instr-ldslicex). | `26` |
-| **`D71B`** | `PLDSLICEXQ` | _`s l - s' -1 or 0`_ | A quiet version of [`LDSLICEXQ`](#instr-ldslicexq). | `26` |
-| **`D71Ccc`** | `[cc+1] LDSLICE_l` | _`s - s'' s'`_ | A longer encoding for [`LDSLICE`](#instr-ldslice). | `34` |
-| **`D71Dcc`** | `[cc+1] PLDSLICE` | _`s - s''`_ | Returns the first `0 < cc+1 <= 256` bits of `s` as `s''`. | `34` |
-| **`D71Ecc`** | `[cc+1] LDSLICEQ` | _`s - s'' s' -1 or s 0`_ | A quiet version of [`LDSLICE`](#instr-ldslice). | `34` |
-| **`D71Fcc`** | `[cc+1] PLDSLICEQ` | _`s - s'' -1 or 0`_ | A quiet version of [`PLDSLICE`](#instr-pldslice). | `34` |
-| **`D720`** | `SDCUTFIRST` | _`s l - s'`_ | Returns the first `0 <= l <= 1023` bits of `s`. It is equivalent to [`PLDSLICEX`](#instr-pldslicex). | `26` |
-| **`D721`** | `SDSKIPFIRST` | _`s l - s'`_ | Returns all but the first `0 <= l <= 1023` bits of `s`. It is equivalent to [`LDSLICEX`](#instr-ldslicex) [`NIP`](#instr-nip). | `26` |
-| **`D722`** | `SDCUTLAST` | _`s l - s'`_ | Returns the last `0 <= l <= 1023` bits of `s`. | `26` |
-| **`D723`** | `SDSKIPLAST` | _`s l - s'`_ | Returns all but the last `0 <= l <= 1023` bits of `s`. | `26` |
-| **`D724`** | `SDSUBSTR` | _`s l l' - s'`_ | Returns `0 <= l' <= 1023` bits of `s` starting from offset `0 <= l <= 1023`, thus extracting a bit substring out of the data of `s`. | `26` |
-| **`D726`** | `SDBEGINSX` | _`s s' - s''`_ | Checks whether `s` begins with (the data bits of) `s'`, and removes `s'` from `s` on success. On failure throws a cell deserialization exception. Primitive [`SDPFXREV`](#instr-sdpfxrev) can be considered a quiet version of [`SDBEGINSX`](#instr-sdbeginsx). | `26` |
-| **`D727`** | `SDBEGINSXQ` | _`s s' - s'' -1 or s 0`_ | A quiet version of [`SDBEGINSX`](#instr-sdbeginsx). | `26` |
-| **`D72A_xsss`** | `[slice] SDBEGINS` | _`s - s''`_ | Checks whether `s` begins with constant bitstring `sss` of length `8x+3` (with continuation bit assumed), where `0 <= x <= 127`, and removes `sss` from `s` on success. | `31` |
-| **`D72E_xsss`** | `[slice] SDBEGINSQ` | _`s - s'' -1 or s 0`_ | A quiet version of [`SDBEGINS`](#instr-sdbegins). | `31` |
-| **`D730`** | `SCUTFIRST` | _`s l r - s'`_ | Returns the first `0 <= l <= 1023` bits and first `0 <= r <= 4` references of `s`. | `26` |
-| **`D731`** | `SSKIPFIRST` | _`s l r - s'`_ | Returns all but the first `l` bits of `s` and `r` references of `s`. | `26` |
-| **`D732`** | `SCUTLAST` | _`s l r - s'`_ | Returns the last `0 <= l <= 1023` data bits and last `0 <= r <= 4` references of `s`. | `26` |
-| **`D733`** | `SSKIPLAST` | _`s l r - s'`_ | Returns all but the last `l` bits of `s` and `r` references of `s`. | `26` |
-| **`D734`** | `SUBSLICE` | _`s l r l' r' - s'`_ | Returns `0 <= l' <= 1023` bits and `0 <= r' <= 4` references from _Slice_ `s`, after skipping the first `0 <= l <= 1023` bits and first `0 <= r <= 4` references. | `26` |
-| **`D736`** | `SPLIT` | _`s l r - s' s''`_ | Splits the first `0 <= l <= 1023` data bits and first `0 <= r <= 4` references from `s` into `s'`, returning the remainder of `s` as `s''`. | `26` |
-| **`D737`** | `SPLITQ` | _`s l r - s' s'' -1 or s 0`_ | A quiet version of [`SPLIT`](#instr-split). | `26` |
-| **`D739`** | | _`c - s ?`_ | Transforms an ordinary or exotic cell into a _Slice_, as if it were an ordinary cell. A flag is returned indicating whether `c` is exotic. If that be the case, its type can later be deserialized from the first eight bits of `s`. | |
-| **`D73A`** | | _`c - c'`_ | Loads an exotic cell `c` and returns an ordinary cell `c'`. If `c` is already ordinary, does nothing. If `c` cannot be loaded, throws an exception. | |
-| **`D73B`** | | _`c - c' -1 or c 0`_ | Loads an exotic cell `c` and returns an ordinary cell `c'`. If `c` is already ordinary, does nothing. If `c` cannot be loaded, returns 0. | |
-| **`D741`** | `SCHKBITS` | _`s l - `_ | Checks whether there are at least `l` data bits in _Slice_ `s`. If this is not the case, throws a cell deserialisation (i.e., cell underflow) exception. | `26/76` |
-| **`D742`** | `SCHKREFS` | _`s r - `_ | Checks whether there are at least `r` references in _Slice_ `s`. | `26/76` |
-| **`D743`** | `SCHKBITREFS` | _`s l r - `_ | Checks whether there are at least `l` data bits and `r` references in _Slice_ `s`. | `26/76` |
-| **`D745`** | `SCHKBITSQ` | _`s l - ?`_ | Checks whether there are at least `l` data bits in _Slice_ `s`. | `26` |
-| **`D746`** | `SCHKREFSQ` | _`s r - ?`_ | Checks whether there are at least `r` references in _Slice_ `s`. | `26` |
-| **`D747`** | `SCHKBITREFSQ` | _`s l r - ?`_ | Checks whether there are at least `l` data bits and `r` references in _Slice_ `s`. | `26` |
-| **`D748`** | `PLDREFVAR` | _`s n - c`_ | Returns the `n`-th cell reference of _Slice_ `s` for `0 <= n <= 3`. | `26` |
-| **`D749`** | `SBITS` | _`s - l`_ | Returns the number of data bits in _Slice_ `s`. | `26` |
-| **`D74A`** | `SREFS` | _`s - r`_ | Returns the number of references in _Slice_ `s`. | `26` |
-| **`D74B`** | `SBITREFS` | _`s - l r`_ | Returns both the number of data bits and the number of references in `s`. | `26` |
-| **`D74E_n`** | `[n] PLDREFIDX` | _`s - c`_ | Returns the `n`-th cell reference of _Slice_ `s`, where `0 <= n <= 3`. | `26` |
-| **`D74C`** | `PLDREF` | _`s - c`_ | Preloads the first cell reference of a _Slice_. | `26` |
-| **`D750`** | `LDILE4` | _`s - x s'`_ | Loads a little-endian signed 32-bit integer. | `26` |
-| **`D751`** | `LDULE4` | _`s - x s'`_ | Loads a little-endian unsigned 32-bit integer. | `26` |
-| **`D752`** | `LDILE8` | _`s - x s'`_ | Loads a little-endian signed 64-bit integer. | `26` |
-| **`D753`** | `LDULE8` | _`s - x s'`_ | Loads a little-endian unsigned 64-bit integer. | `26` |
-| **`D754`** | `PLDILE4` | _`s - x`_ | Preloads a little-endian signed 32-bit integer. | `26` |
-| **`D755`** | `PLDULE4` | _`s - x`_ | Preloads a little-endian unsigned 32-bit integer. | `26` |
-| **`D756`** | `PLDILE8` | _`s - x`_ | Preloads a little-endian signed 64-bit integer. | `26` |
-| **`D757`** | `PLDULE8` | _`s - x`_ | Preloads a little-endian unsigned 64-bit integer. | `26` |
-| **`D758`** | `LDILE4Q` | _`s - x s' -1 or s 0`_ | Quietly loads a little-endian signed 32-bit integer. | `26` |
-| **`D759`** | `LDULE4Q` | _`s - x s' -1 or s 0`_ | Quietly loads a little-endian unsigned 32-bit integer. | `26` |
-| **`D75A`** | `LDILE8Q` | _`s - x s' -1 or s 0`_ | Quietly loads a little-endian signed 64-bit integer. | `26` |
-| **`D75B`** | `LDULE8Q` | _`s - x s' -1 or s 0`_ | Quietly loads a little-endian unsigned 64-bit integer. | `26` |
-| **`D75C`** | `PLDILE4Q` | _`s - x -1 or 0`_ | Quietly preloads a little-endian signed 32-bit integer. | `26` |
-| **`D75D`** | `PLDULE4Q` | _`s - x -1 or 0`_ | Quietly preloads a little-endian unsigned 32-bit integer. | `26` |
-| **`D75E`** | `PLDILE8Q` | _`s - x -1 or 0`_ | Quietly preloads a little-endian signed 64-bit integer. | `26` |
-| **`D75F`** | `PLDULE8Q` | _`s - x -1 or 0`_ | Quietly preloads a little-endian unsigned 64-bit integer. | `26` |
-| **`D760`** | `LDZEROES` | _`s - n s'`_ | Returns the count `n` of leading zero bits in `s`, and removes these bits from `s`. | `26` |
-| **`D761`** | `LDONES` | _`s - n s'`_ | Returns the count `n` of leading one bits in `s`, and removes these bits from `s`. | `26` |
-| **`D762`** | `LDSAME` | _`s x - n s'`_ | Returns the count `n` of leading bits equal to `0 <= x <= 1` in `s`, and removes these bits from `s`. | `26` |
-| **`D764`** | `SDEPTH` | _`s - x`_ | Returns the depth of _Slice_ `s`. If `s` has no references, then `x=0`; otherwise `x` is one plus the maximum of depths of cells referred to from `s`. | `26` |
-| **`D765`** | `CDEPTH` | _`c - x`_ | Returns the depth of _Cell_ `c`. If `c` has no references, then `x=0`; otherwise `x` is one plus the maximum of depths of cells referred to from `c`. If `c` is a _Null_ instead of a _Cell_, returns zero. | `26` |
-
-## 8 Continuation and control flow primitives
-### 8.1 Unconditional control flow primitives
-| xxxxxxx Opcode | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description | xxxx Gas |
-|:-|:-|:-|:-|:-|
-| **`D8`** | `EXECUTE` `CALLX` | _`c - `_ | _Calls_, or _executes_, continuation `c`. | `18` |
-| **`D9`** | `JMPX` | _`c - `_ | _Jumps_, or transfers control, to continuation `c`. The remainder of the previous current continuation `cc` is discarded. | `18` |
-| **`DApr`** | `[p] [r] CALLXARGS` | _`c - `_ | _Calls_ continuation `c` with `p` parameters and expecting `r` return values `0 <= p <= 15`, `0 <= r <= 15` | `26` |
-| **`DB0p`** | `[p] -1 CALLXARGS` | _`c - `_ | _Calls_ continuation `c` with `0 <= p <= 15` parameters, expecting an arbitrary number of return values. | `26` |
-| **`DB1p`** | `[p] JMPXARGS` | _`c - `_ | _Jumps_ to continuation `c`, passing only the top `0 <= p <= 15` values from the current stack to it (the remainder of the current stack is discarded). | `26` |
-| **`DB2r`** | `[r] RETARGS` | | _Returns_ to `c0`, with `0 <= r <= 15` return values taken from the current stack. | `26` |
-| **`DB30`** | `RET` `RETTRUE` | | _Returns_ to the continuation at `c0`. The remainder of the current continuation `cc` is discarded. Approximately equivalent to [`c0 PUSHCTR`](#instr-pushctr) [`JMPX`](#instr-jmpx). | `26` |
-| **`DB31`** | `RETALT` `RETFALSE` | | _Returns_ to the continuation at `c1`. Approximately equivalent to [`c1 PUSHCTR`](#instr-pushctr) [`JMPX`](#instr-jmpx). | `26` |
-| **`DB32`** | `BRANCH` `RETBOOL` | _`f - `_ | Performs [`RETTRUE`](#instr-ret) if integer `f!=0`, or [`RETFALSE`](#instr-retalt) if `f=0`. | `26` |
-| **`DB34`** | `CALLCC` | _`c - `_ | _Call with current continuation_, transfers control to `c`, pushing the old value of `cc` into `c`'s stack (instead of discarding it or writing it into new `c0`). | `26` |
-| **`DB35`** | `JMPXDATA` | _`c - `_ | Similar to [`CALLCC`](#instr-callcc), but the remainder of the current continuation (the old value of `cc`) is converted into a _Slice_ before pushing it into the stack of `c`. | `26` |
-| **`DB36pr`** | `[p] [r] CALLCCARGS` | _`c - `_ | Similar to [`CALLXARGS`](#instr-callxargs), but pushes the old value of `cc` (along with the top `0 <= p <= 15` values from the original stack) into the stack of newly-invoked continuation `c`, setting `cc.nargs` to `-1 <= r <= 14`. | `34` |
-| **`DB38`** | `CALLXVARARGS` | _`c p r - `_ | Similar to [`CALLXARGS`](#instr-callxargs), but takes `-1 <= p,r <= 254` from the stack. The next three operations also take `p` and `r` from the stack, both in the range `-1...254`. | `26` |
-| **`DB39`** | `RETVARARGS` | _`p r - `_ | Similar to [`RETARGS`](#instr-retargs). | `26` |
-| **`DB3A`** | `JMPXVARARGS` | _`c p r - `_ | Similar to [`JMPXARGS`](#instr-jmpxargs). | `26` |
-| **`DB3B`** | `CALLCCVARARGS` | _`c p r - `_ | Similar to [`CALLCCARGS`](#instr-callccargs). | `26` |
-| **`DB3C`** | `[ref] CALLREF` | | Equivalent to [`PUSHREFCONT`](#instr-pushrefcont) [`CALLX`](#instr-execute). | `126/51` |
-| **`DB3D`** | `[ref] JMPREF` | | Equivalent to [`PUSHREFCONT`](#instr-pushrefcont) [`JMPX`](#instr-jmpx). | `126/51` |
-| **`DB3E`** | `[ref] JMPREFDATA` | | Equivalent to [`PUSHREFCONT`](#instr-pushrefcont) [`JMPXDATA`](#instr-jmpxdata). | `126/51` |
-| **`DB3F`** | `RETDATA` | | Equivalent to [`c0 PUSHCTR`](#instr-pushctr) [`JMPXDATA`](#instr-jmpxdata). In this way, the remainder of the current continuation is converted into a _Slice_ and returned to the caller. | `26` |
-### 8.2 Conditional control flow primitives
-| xxxxxxx Opcode | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description | xxxx Gas |
-|:-|:-|:-|:-|:-|
-| **`DC`** | `IFRET` `IFNOT:` | _`f - `_ | Performs a [`RET`](#instr-ret), but only if integer `f` is non-zero. If `f` is a `NaN`, throws an integer overflow exception. | `18` |
-| **`DD`** | `IFNOTRET` `IF:` | _`f - `_ | Performs a [`RET`](#instr-ret), but only if integer `f` is zero. | `18` |
-| **`DE`** | `IF` | _`f c - `_ | Performs [`EXECUTE`](#instr-execute) for `c` (i.e., _executes_ `c`), but only if integer `f` is non-zero. Otherwise simply discards both values. | `18` |
-| **`DE`** | `IF:<{ code }>` `<{ code }>IF` | _`f -`_ | Equivalent to [`<{ code }> CONT`](#instr-pushcont) [`IF`](#instr-if). | |
-| **`DF`** | `IFNOT` | _`f c - `_ | Executes continuation `c`, but only if integer `f` is zero. Otherwise simply discards both values. | `18` |
-| **`DF`** | `IFNOT:<{ code }>` `<{ code }>IFNOT` | _`f -`_ | Equivalent to [`<{ code }> CONT`](#instr-pushcont) [`IFNOT`](#instr-ifnot). | |
-| **`E0`** | `IFJMP` | _`f c - `_ | Jumps to `c` (similarly to [`JMPX`](#instr-jmpx)), but only if `f` is non-zero. | `18` |
-| **`E0`** | `IFJMP:<{ code }>` | _`f -`_ | Equivalent to [`<{ code }> CONT`](#instr-pushcont) [`IFJMP`](#instr-ifjmp). | |
-| **`E1`** | `IFNOTJMP` | _`f c - `_ | Jumps to `c` (similarly to [`JMPX`](#instr-jmpx)), but only if `f` is zero. | `18` |
-| **`E1`** | `IFNOTJMP:<{ code }>` | _`f -`_ | Equivalent to [`<{ code }> CONT`](#instr-pushcont) [`IFNOTJMP`](#instr-ifnotjmp). | |
-| **`E2`** | `IFELSE` | _`f c c' - `_ | If integer `f` is non-zero, executes `c`, otherwise executes `c'`. Equivalent to [`CONDSELCHK`](#instr-condselchk) [`EXECUTE`](#instr-execute). | `18` |
-| **`E2`** | `IF:<{ code1 }>ELSE<{ code2 }>` | _`f -`_ | Equivalent to [`<{ code1 }> CONT`](#instr-pushcont) [`<{ code2 }> CONT`](#instr-pushcont) [`IFELSE`](#instr-ifelse). | |
-| **`E300`** | `[ref] IFREF` | _`f - `_ | Equivalent to [`PUSHREFCONT`](#instr-pushrefcont) [`IF`](#instr-if), with the optimization that the cell reference is not actually loaded into a _Slice_ and then converted into an ordinary _Continuation_ if `f=0`. Gas consumption of this primitive depends on whether `f=0` and whether the reference was loaded before. Similar remarks apply other primitives that accept a continuation as a reference. | `26/126/51` |
-| **`E301`** | `[ref] IFNOTREF` | _`f - `_ | Equivalent to [`PUSHREFCONT`](#instr-pushrefcont) [`IFNOT`](#instr-ifnot). | `26/126/51` |
-| **`E302`** | `[ref] IFJMPREF` | _`f - `_ | Equivalent to [`PUSHREFCONT`](#instr-pushrefcont) [`IFJMP`](#instr-ifjmp). | `26/126/51` |
-| **`E303`** | `[ref] IFNOTJMPREF` | _`f - `_ | Equivalent to [`PUSHREFCONT`](#instr-pushrefcont) [`IFNOTJMP`](#instr-ifnotjmp). | `26/126/51` |
-| **`E304`** | `CONDSEL` | _`f x y - x or y`_ | If integer `f` is non-zero, returns `x`, otherwise returns `y`. Notice that no type checks are performed on `x` and `y`; as such, it is more like a conditional stack operation. Roughly equivalent to [`ROT`](#instr-rot) [`ISZERO`](#instr-iszero) [`INC`](#instr-inc) [`ROLLX`](#instr-rollx) [`NIP`](#instr-nip). | `26` |
-| **`E305`** | `CONDSELCHK` | _`f x y - x or y`_ | Same as [`CONDSEL`](#instr-condsel), but first checks whether `x` and `y` have the same type. | `26` |
-| **`E308`** | `IFRETALT` | _`f -`_ | Performs [`RETALT`](#instr-retalt) if integer `f!=0`. | `26` |
-| **`E309`** | `IFNOTRETALT` | _`f -`_ | Performs [`RETALT`](#instr-retalt) if integer `f=0`. | `26` |
-| **`E30D`** | `[ref] IFREFELSE` | _`f c -`_ | Equivalent to [`PUSHREFCONT`](#instr-pushrefcont) [`SWAP`](#instr-swap) [`IFELSE`](#instr-ifelse), with the optimization that the cell reference is not actually loaded into a _Slice_ and then converted into an ordinary _Continuation_ if `f=0`. Similar remarks apply to the next two primitives: cells are converted into continuations only when necessary. | `26/126/51` |
-| **`E30E`** | `[ref] IFELSEREF` | _`f c -`_ | Equivalent to [`PUSHREFCONT`](#instr-pushrefcont) [`IFELSE`](#instr-ifelse). | `26/126/51` |
-| **`E30F`** | `[ref] [ref] IFREFELSEREF` | _`f -`_ | Equivalent to [`PUSHREFCONT`](#instr-pushrefcont) [`PUSHREFCONT`](#instr-pushrefcont) [`IFELSE`](#instr-ifelse). | `126/51` |
-| **`E39_n`** | `[n] IFBITJMP` | _`x c - x`_ | Checks whether bit `0 <= n <= 31` is set in integer `x`, and if so, performs [`JMPX`](#instr-jmpx) to continuation `c`. Value `x` is left in the stack. | `26` |
-| **`E3B_n`** | `[n] IFNBITJMP` | _`x c - x`_ | Jumps to `c` if bit `0 <= n <= 31` is not set in integer `x`. | `26` |
-| **`E3D_n`** | `[ref] [n] IFBITJMPREF` | _`x - x`_ | Performs a [`JMPREF`](#instr-jmpref) if bit `0 <= n <= 31` is set in integer `x`. | `126/51` |
-| **`E3F_n`** | `[ref] [n] IFNBITJMPREF` | _`x - x`_ | Performs a [`JMPREF`](#instr-jmpref) if bit `0 <= n <= 31` is not set in integer `x`. | `126/51` |
-### 8.3 Control flow primitives: loops
-| xxxxxxx Opcode | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description | xxxx Gas |
-|:-|:-|:-|:-|:-|
-| **`E4`** | `REPEAT` | _`n c - `_ | Executes continuation `c` `n` times, if integer `n` is non-negative. If `n>=2^31` or `n<-2^31`, generates a range check exception. Notice that a [`RET`](#instr-ret) inside the code of `c` works as a `continue`, not as a `break`. One should use either alternative (experimental) loops or alternative [`RETALT`](#instr-retalt) (along with a [`SETEXITALT`](#instr-setexitalt) before the loop) to `break` out of a loop. | `18` |
-| **`E4`** | `REPEAT:<{ code }>` `<{ code }>REPEAT` | _`n -`_ | Equivalent to [`<{ code }> CONT`](#instr-pushcont) [`REPEAT`](#instr-repeat). | |
-| **`E5`** | `REPEATEND` `REPEAT:` | _`n - `_ | Similar to [`REPEAT`](#instr-repeat), but it is applied to the current continuation `cc`. | `18` |
-| **`E6`** | `UNTIL` | _`c - `_ | Executes continuation `c`, then pops an integer `x` from the resulting stack. If `x` is zero, performs another iteration of this loop. The actual implementation of this primitive involves an extraordinary continuation `ec_until` with its arguments set to the body of the loop (continuation `c`) and the original current continuation `cc`. This extraordinary continuation is then saved into the savelist of `c` as `c.c0` and the modified `c` is then executed. The other loop primitives are implemented similarly with the aid of suitable extraordinary continuations. | `18` |
-| **`E6`** | `UNTIL:<{ code }>` `<{ code }>UNTIL` | _`-`_ | Equivalent to [`<{ code }> CONT`](#instr-pushcont) [`UNTIL`](#instr-until). | |
-| **`E7`** | `UNTILEND` `UNTIL:` | _`-`_ | Similar to [`UNTIL`](#instr-until), but executes the current continuation `cc` in a loop. When the loop exit condition is satisfied, performs a [`RET`](#instr-ret). | `18` |
-| **`E8`** | `WHILE` | _`c' c - `_ | Executes `c'` and pops an integer `x` from the resulting stack. If `x` is zero, exists the loop and transfers control to the original `cc`. If `x` is non-zero, executes `c`, and then begins a new iteration. | `18` |
-| **`E8`** | `WHILE:<{ cond }>DO<{ code }>` | _`-`_ | Equivalent to [`<{ cond }> CONT`](#instr-pushcont) [`<{ code }> CONT`](#instr-pushcont) [`WHILE`](#instr-while). | |
-| **`E9`** | `WHILEEND` | _`c' - `_ | Similar to [`WHILE`](#instr-while), but uses the current continuation `cc` as the loop body. | `18` |
-| **`EA`** | `AGAIN` | _`c - `_ | Similar to [`REPEAT`](#instr-repeat), but executes `c` infinitely many times. A [`RET`](#instr-ret) only begins a new iteration of the infinite loop, which can be exited only by an exception, or a [`RETALT`](#instr-retalt) (or an explicit [`JMPX`](#instr-jmpx)). | `18` |
-| **`EA`** | `AGAIN:<{ code }>` `<{ code }>AGAIN` | _`-`_ | Equivalent to [`<{ code }> CONT`](#instr-pushcont) [`AGAIN`](#instr-again). | |
-| **`EB`** | `AGAINEND` `AGAIN:` | _`-`_ | Similar to [`AGAIN`](#instr-again), but performed with respect to the current continuation `cc`. | `18` |
-| **`E314`** | `REPEATBRK` | _`n c -`_ | Similar to [`REPEAT`](#instr-repeat), but also sets `c1` to the original `cc` after saving the old value of `c1` into the savelist of the original `cc`. In this way [`RETALT`](#instr-retalt) could be used to break out of the loop body. | `26` |
-| **`E314`** | `REPEATBRK:<{ code }>` `<{ code }>REPEATBRK` | _`n -`_ | Equivalent to [`<{ code }> CONT`](#instr-pushcont) [`REPEATBRK`](#instr-repeatbrk). | |
-| **`E315`** | `REPEATENDBRK` | _`n -`_ | Similar to [`REPEATEND`](#instr-repeatend), but also sets `c1` to the original `c0` after saving the old value of `c1` into the savelist of the original `c0`. Equivalent to [`SAMEALTSAVE`](#instr-samealtsave) [`REPEATEND`](#instr-repeatend). | `26` |
-| **`E316`** | `UNTILBRK` | _`c -`_ | Similar to [`UNTIL`](#instr-until), but also modifies `c1` in the same way as [`REPEATBRK`](#instr-repeatbrk). | `26` |
-| **`E316`** | `UNTILBRK:<{ code }>` | _`-`_ | Equivalent to [`<{ code }> CONT`](#instr-pushcont) [`UNTILBRK`](#instr-untilbrk). | |
-| **`E317`** | `UNTILENDBRK` `UNTILBRK:` | _`-`_ | Equivalent to [`SAMEALTSAVE`](#instr-samealtsave) [`UNTILEND`](#instr-untilend). | `26` |
-| **`E318`** | `WHILEBRK` | _`c' c -`_ | Similar to [`WHILE`](#instr-while), but also modifies `c1` in the same way as [`REPEATBRK`](#instr-repeatbrk). | `26` |
-| **`E318`** | `WHILEBRK:<{ cond }>DO<{ code }>` | _`-`_ | Equivalent to [`<{ cond }> CONT`](#instr-pushcont) [`<{ code }> CONT`](#instr-pushcont) [`WHILEBRK`](#instr-whilebrk). | |
-| **`E319`** | `WHILEENDBRK` | _`c -`_ | Equivalent to [`SAMEALTSAVE`](#instr-samealtsave) [`WHILEEND`](#instr-whileend). | `26` |
-| **`E31A`** | `AGAINBRK` | _`c -`_ | Similar to [`AGAIN`](#instr-again), but also modifies `c1` in the same way as [`REPEATBRK`](#instr-repeatbrk). | `26` |
-| **`E31A`** | `AGAINBRK:<{ code }>` | _`-`_ | Equivalent to [`<{ code }> CONT`](#instr-pushcont) [`AGAINBRK`](#instr-againbrk). | |
-| **`E31B`** | `AGAINENDBRK` `AGAINBRK:` | _`-`_ | Equivalent to [`SAMEALTSAVE`](#instr-samealtsave) [`AGAINEND`](#instr-againend). | `26` |
-### 8.4 Manipulating the stack of continuations
-Here `s"` is the [fee for moving stack elements between continuations](#11-gas-prices). It is equal to the size of the resulting stack minus 32 (or 0 if the stack is smaller than 32).
-
-| xxxxxxx Opcode | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description | xxxx Gas |
-|:-|:-|:-|:-|:-|
-| **`ECrn`** | `[r] [n] SETCONTARGS` | _`x_1 x_2...x_r c - c'`_ | Similar to [`[r] -1 SETCONTARGS`](#instr-setcontargs-n), but sets `c.nargs` to the final size of the stack of `c'` plus `n`. In other words, transforms `c` into a _closure_ or a _partially applied function_, with `0 <= n <= 14` arguments missing. | `26+s”` |
-| **`EC0n`** | `[n] SETNUMARGS` | _`c - c'`_ | Sets `c.nargs` to `n` plus the current depth of `c`'s stack, where `0 <= n <= 14`. If `c.nargs` is already set to a non-negative value, does nothing. | `26` |
-| **`ECrF`** | `[r] -1 SETCONTARGS` | _`x_1 x_2...x_r c - c'`_ | Pushes `0 <= r <= 15` values `x_1...x_r` into the stack of (a copy of) the continuation `c`, starting with `x_1`. If the final depth of `c`'s stack turns out to be greater than `c.nargs`, a stack overflow exception is generated. | `26+s”` |
-| **`ED0p`** | `[p] RETURNARGS` | _`-`_ | Leaves only the top `0 <= p <= 15` values in the current stack (somewhat similarly to [`ONLYTOPX`](#instr-onlytopx)), with all the unused bottom values not discarded, but saved into continuation `c0` in the same way as [`SETCONTARGS`](#instr-setcontargs-n) does. | `26+s”` |
-| **`ED10`** | `RETURNVARARGS` | _`p -`_ | Similar to [`RETURNARGS`](#instr-returnargs), but with Integer `0 <= p <= 255` taken from the stack. | `26+s”` |
-| **`ED11`** | `SETCONTVARARGS` | _`x_1 x_2...x_r c r n - c'`_ | Similar to [`SETCONTARGS`](#instr-setcontargs-n), but with `0 <= r <= 255` and `-1 <= n <= 255` taken from the stack. | `26+s”` |
-| **`ED12`** | `SETNUMVARARGS` | _`c n - c'`_ | `-1 <= n <= 255` If `n=-1`, this operation does nothing (`c'=c`). Otherwise its action is similar to [`[n] SETNUMARGS`](#instr-setnumargs), but with `n` taken from the stack. | `26` |
-### 8.5 Creating simple continuations and closures
-| xxxxxxx Opcode | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description | xxxx Gas |
-|:-|:-|:-|:-|:-|
-| **`ED1E`** | `BLESS` | _`s - c`_ | Transforms a _Slice_ `s` into a simple ordinary continuation `c`, with `c.code=s` and an empty stack and savelist. | `26` |
-| **`ED1F`** | `BLESSVARARGS` | _`x_1...x_r s r n - c`_ | Equivalent to [`ROT`](#instr-rot) [`BLESS`](#instr-bless) [`ROTREV`](#instr-rotrev) [`SETCONTVARARGS`](#instr-setcontvarargs). | `26+s”` |
-| **`EErn`** | `[r] [n] BLESSARGS` | _`x_1...x_r s - c`_ | `0 <= r <= 15`, `-1 <= n <= 14` Equivalent to [`BLESS`](#instr-bless) [`[r] [n] SETCONTARGS`](#instr-setcontargs-n). The value of `n` is represented inside the instruction by the 4-bit integer `n mod 16`. | `26` |
-| **`EE0n`** | `[n] BLESSNUMARGS` | _`s - c`_ | Also transforms a _Slice_ `s` into a _Continuation_ `c`, but sets `c.nargs` to `0 <= n <= 14`. | `26` |
-### 8.6 Operations with continuation savelists and control registers
-| xxxxxxx Opcode | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description | xxxx Gas |
-|:-|:-|:-|:-|:-|
-| **`ED4i`** | `c[i] PUSHCTR` `c[i] PUSH` | _`- x`_ | Pushes the current value of control register `c(i)`. If the control register is not supported in the current codepage, or if it does not have a value, an exception is triggered. | `26` |
-| **`ED44`** | `c4 PUSHCTR` `c4 PUSH` | _`- x`_ | Pushes the “global data root'' cell reference, thus enabling access to persistent smart-contract data. | `26` |
-| **`ED5i`** | `c[i] POPCTR` `c[i] POP` | _`x - `_ | Pops a value `x` from the stack and stores it into control register `c(i)`, if supported in the current codepage. Notice that if a control register accepts only values of a specific type, a type-checking exception may occur. | `26` |
-| **`ED54`** | `c4 POPCTR` `c4 POP` | _`x -`_ | Sets the “global data root'' cell reference, thus allowing modification of persistent smart-contract data. | `26` |
-| **`ED6i`** | `c[i] SETCONT` `c[i] SETCONTCTR` | _`x c - c'`_ | Stores `x` into the savelist of continuation `c` as `c(i)`, and returns the resulting continuation `c'`. Almost all operations with continuations may be expressed in terms of [`SETCONTCTR`](#instr-setcontctr), [`POPCTR`](#instr-popctr), and [`PUSHCTR`](#instr-pushctr). | `26` |
-| **`ED7i`** | `c[i] SETRETCTR` | _`x - `_ | Equivalent to [`c0 PUSHCTR`](#instr-pushctr) [`c[i] SETCONTCTR`](#instr-setcontctr) [`c0 POPCTR`](#instr-popctr). | `26` |
-| **`ED8i`** | `c[i] SETALTCTR` | _`x - `_ | Equivalent to [`c1 PUSHCTR`](#instr-pushctr) [`c[i] SETCONTCTR`](#instr-setcontctr) [`c0 POPCTR`](#instr-popctr). | `26` |
-| **`ED9i`** | `c[i] POPSAVE` `c[i] POPCTRSAVE` | _`x -`_ | Similar to [`c[i] POPCTR`](#instr-popctr), but also saves the old value of `c[i]` into continuation `c0`. Equivalent (up to exceptions) to [`c[i] SAVECTR`](#instr-save) [`c[i] POPCTR`](#instr-popctr). | `26` |
-| **`EDAi`** | `c[i] SAVE` `c[i] SAVECTR` | | Saves the current value of `c(i)` into the savelist of continuation `c0`. If an entry for `c[i]` is already present in the savelist of `c0`, nothing is done. Equivalent to [`c[i] PUSHCTR`](#instr-pushctr) [`c[i] SETRETCTR`](#instr-setretctr). | `26` |
-| **`EDBi`** | `c[i] SAVEALT` `c[i] SAVEALTCTR` | | Similar to [`c[i] SAVE`](#instr-save), but saves the current value of `c[i]` into the savelist of `c1`, not `c0`. | `26` |
-| **`EDCi`** | `c[i] SAVEBOTH` `c[i] SAVEBOTHCTR` | | Equivalent to [`DUP`](#instr-dup) [`c[i] SAVE`](#instr-save) [`c[i] SAVEALT`](#instr-savealt). | `26` |
-| **`EDE0`** | `PUSHCTRX` | _`i - x`_ | Similar to [`c[i] PUSHCTR`](#instr-pushctr), but with `i`, `0 <= i <= 255`, taken from the stack. Notice that this primitive is one of the few “exotic'' primitives, which are not polymorphic like stack manipulation primitives, and at the same time do not have well-defined types of parameters and return values, because the type of `x` depends on `i`. | `26` |
-| **`EDE1`** | `POPCTRX` | _`x i - `_ | Similar to [`c[i] POPCTR`](#instr-popctr), but with `0 <= i <= 255` from the stack. | `26` |
-| **`EDE2`** | `SETCONTCTRX` | _`x c i - c'`_ | Similar to [`c[i] SETCONTCTR`](#instr-setcontctr), but with `0 <= i <= 255` from the stack. | `26` |
-| **`EDF0`** | `COMPOS` `BOOLAND` | _`c c' - c''`_ | Computes the composition `compose0(c, c’)`, which has the meaning of “perform `c`, and, if successful, perform `c'`'' (if `c` is a boolean circuit) or simply “perform `c`, then `c'`''. Equivalent to [`SWAP`](#instr-swap) [`c0 SETCONT`](#instr-setcontctr). | `26` |
-| **`EDF1`** | `COMPOSALT` `BOOLOR` | _`c c' - c''`_ | Computes the alternative composition `compose1(c, c’)`, which has the meaning of “perform `c`, and, if not successful, perform `c'`'' (if `c` is a boolean circuit). Equivalent to [`SWAP`](#instr-swap) [`c1 SETCONT`](#instr-setcontctr). | `26` |
-| **`EDF2`** | `COMPOSBOTH` | _`c c' - c''`_ | Computes composition `compose1(compose0(c, c’), c’)`, which has the meaning of “compute boolean circuit `c`, then compute `c'`, regardless of the result of `c`''. | `26` |
-| **`EDF3`** | `ATEXIT` | _`c - `_ | Sets `c0` to `compose0(c, c0)`. In other words, `c` will be executed before exiting current subroutine. | `26` |
-| **`EDF3`** | `ATEXIT:<{ code }>` `<{ code }>ATEXIT` | _`-`_ | Equivalent to [`<{ code }> CONT`](#instr-pushcont) [`ATEXIT`](#instr-atexit). | |
-| **`EDF4`** | `ATEXITALT` | _`c - `_ | Sets `c1` to `compose1(c, c1)`. In other words, `c` will be executed before exiting current subroutine by its alternative return path. | `26` |
-| **`EDF4`** | `ATEXITALT:<{ code }>` `<{ code }>ATEXITALT` | _`-`_ | Equivalent to [`<{ code }> CONT`](#instr-pushcont) [`ATEXITALT`](#instr-atexitalt). | |
-| **`EDF5`** | `SETEXITALT` | _`c - `_ | Sets `c1` to `compose1(compose0(c, c0), c1)`, In this way, a subsequent [`RETALT`](#instr-retalt) will first execute `c`, then transfer control to the original `c0`. This can be used, for instance, to exit from nested loops. | `26` |
-| **`EDF6`** | `THENRET` | _`c - c'`_ | Computes `compose0(c, c0)`. | `26` |
-| **`EDF7`** | `THENRETALT` | _`c - c'`_ | Computes `compose0(c, c1)` | `26` |
-| **`EDF8`** | `INVERT` | _`-`_ | Interchanges `c0` and `c1`. | `26` |
-| **`EDF9`** | `BOOLEVAL` | _`c - ?`_ | Performs `cc:=compose1(compose0(c, compose0(-1 PUSHINT, cc)), compose0(0 PUSHINT, cc))`. If `c` represents a boolean circuit, the net effect is to evaluate it and push either `-1` or `0` into the stack before continuing. | `26` |
-| **`EDFA`** | `SAMEALT` | _`-`_ | Sets `c1` to `c0`. Equivalent to [`c0 PUSHCTR`](#instr-pushctr) [`c1 POPCTR`](#instr-popctr). | `26` |
-| **`EDFB`** | `SAMEALTSAVE` | _`-`_ | Sets `c1` to `c0`, but first saves the old value of `c1` into the savelist of `c0`. Equivalent to [`c1 SAVE`](#instr-save) [`SAMEALT`](#instr-samealt). | `26` |
-### 8.7 Dictionary subroutine calls and jumps
-| xxxxxxx Opcode | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description | xxxx Gas |
-|:-|:-|:-|:-|:-|
-| **`F0nn`** | `[nn] CALL` `[nn] CALLDICT` | _`- nn`_ | Calls the continuation in `c3`, pushing integer `0 <= nn <= 255` into its stack as an argument. Approximately equivalent to [`[nn] PUSHINT`](#instr-pushint-4) [`c3 PUSHCTR`](#instr-pushctr) [`EXECUTE`](#instr-execute). | |
-| **`F12_n`** | `[n] CALL` `[n] CALLDICT` | _`- n`_ | For `0 <= n < 2^14`, an encoding of [`[n] CALL`](#instr-calldict) for larger values of `n`. | |
-| **`F16_n`** | `[n] JMP` | _` - n`_ | Jumps to the continuation in `c3`, pushing integer `0 <= n < 2^14` as its argument. Approximately equivalent to [`n PUSHINT`](#instr-pushint-4) [`c3 PUSHCTR`](#instr-pushctr) [`JMPX`](#instr-jmpx). | |
-| **`F1A_n`** | `[n] PREPARE` `[n] PREPAREDICT` | _` - n c`_ | Equivalent to [`n PUSHINT`](#instr-pushint-4) [`c3 PUSHCTR`](#instr-pushctr), for `0 <= n < 2^14`. In this way, [`[n] CALL`](#instr-calldict) is approximately equivalent to [`[n] PREPARE`](#instr-preparedict) [`EXECUTE`](#instr-execute), and [`[n] JMP`](#instr-jmpdict) is approximately equivalent to [`[n] PREPARE`](#instr-preparedict) [`JMPX`](#instr-jmpx). One might use, for instance, [`CALLXARGS`](#instr-callxargs) or [`CALLCC`](#instr-callcc) instead of [`EXECUTE`](#instr-execute) here. | |
-
-## 9 Exception generating and handling primitives
-| xxxxxxx Opcode | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description | xxxx Gas |
-|:-|:-|:-|:-|:-|
-| **`F22_n`** | `[n] THROW` | _` - 0 n`_ | Throws exception `0 <= n <= 63` with parameter zero. In other words, it transfers control to the continuation in `c2`, pushing `0` and `n` into its stack, and discarding the old stack altogether. | `76` |
-| **`F26_n`** | `[n] THROWIF` | _`f - `_ | Throws exception `0 <= n <= 63` with parameter zero only if integer `f!=0`. | `26/76` |
-| **`F2A_n`** | `[n] THROWIFNOT` | _`f - `_ | Throws exception `0 <= n <= 63` with parameter zero only if integer `f=0`. | `26/76` |
-| **`F2C4_n`** | `[n] THROW` | _`- 0 nn`_ | For `0 <= n < 2^11`, an encoding of [`[n] THROW`](#instr-throw-short) for larger values of `n`. | `84` |
-| **`F2CC_n`** | `[n] THROWARG` | _`x - x nn`_ | Throws exception `0 <= n < 2^11` with parameter `x`, by copying `x` and `n` into the stack of `c2` and transferring control to `c2`. | `84` |
-| **`F2D4_n`** | `[n] THROWIF` | _`f - `_ | For `0 <= n < 2^11`, an encoding of [`[n] THROWIF`](#instr-throwif-short) for larger values of `n`. | `34/84` |
-| **`F2DC_n`** | `[n] THROWARGIF` | _`x f - `_ | Throws exception `0 <= nn < 2^11` with parameter `x` only if integer `f!=0`. | `34/84` |
-| **`F2E4_n`** | `[n] THROWIFNOT` | _`f - `_ | For `0 <= n < 2^11`, an encoding of [`[n] THROWIFNOT`](#instr-throwifnot-short) for larger values of `n`. | `34/84` |
-| **`F2EC_n`** | `[n] THROWARGIFNOT` | _`x f - `_ | Throws exception `0 <= n < 2^11` with parameter `x` only if integer `f=0`. | `34/84` |
-| **`F2F0`** | `THROWANY` | _`n - 0 n`_ | Throws exception `0 <= n < 2^16` with parameter zero. Approximately equivalent to [`ZERO`](#instr-zero) [`SWAP`](#instr-swap) [`THROWARGANY`](#instr-throwargany). | `76` |
-| **`F2F1`** | `THROWARGANY` | _`x n - x n`_ | Throws exception `0 <= n < 2^16` with parameter `x`, transferring control to the continuation in `c2`. Approximately equivalent to [`c2 PUSHCTR`](#instr-pushctr) [`2 JMPXARGS`](#instr-jmpxargs). | `76` |
-| **`F2F2`** | `THROWANYIF` | _`n f - `_ | Throws exception `0 <= n < 2^16` with parameter zero only if `f!=0`. | `26/76` |
-| **`F2F3`** | `THROWARGANYIF` | _`x n f - `_ | Throws exception `0 <= n<2^16` with parameter `x` only if `f!=0`. | `26/76` |
-| **`F2F4`** | `THROWANYIFNOT` | _`n f - `_ | Throws exception `0 <= n<2^16` with parameter zero only if `f=0`. | `26/76` |
-| **`F2F5`** | `THROWARGANYIFNOT` | _`x n f - `_ | Throws exception `0 <= n<2^16` with parameter `x` only if `f=0`. | `26/76` |
-| **`F2FF`** | `TRY` | _`c c' - `_ | Sets `c2` to `c'`, first saving the old value of `c2` both into the savelist of `c'` and into the savelist of the current continuation, which is stored into `c.c0` and `c'.c0`. Then runs `c` similarly to [`EXECUTE`](#instr-execute). If `c` does not throw any exceptions, the original value of `c2` is automatically restored on return from `c`. If an exception occurs, the execution is transferred to `c'`, but the original value of `c2` is restored in the process, so that `c'` can re-throw the exception by [`THROWANY`](#instr-throwany) if it cannot handle it by itself. | `26` |
-| **`F2FF`** | `TRY:<{ code1 }>CATCH<{ code2 }>` | _`-`_ | Equivalent to [`<{ code1 }> CONT`](#instr-pushcont) [`<{ code2 }> CONT`](#instr-pushcont) [`TRY`](#instr-try). | |
-| **`F3pr`** | `[p] [r] TRYARGS` | _`c c' - `_ | Similar to [`TRY`](#instr-try), but with [`[p] [r] CALLXARGS`](#instr-callxargs) internally used instead of [`EXECUTE`](#instr-execute). In this way, all but the top `0 <= p <= 15` stack elements will be saved into current continuation's stack, and then restored upon return from either `c` or `c'`, with the top `0 <= r <= 15` values of the resulting stack of `c` or `c'` copied as return values. | `26` |
-
-## 10 Dictionary manipulation primitives
-The gas consumption of most dictionary operations is not fixed, it depends on the contents of the given dictionary.
-### 10.1 Dictionary creation
-| xxxxxxx Opcode | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description | xxxx Gas |
-|:-|:-|:-|:-|:-|
-| **`6D`** | `NEWDICT` | _` - D`_ | Returns a new empty dictionary. It is an alternative mnemonics for [`PUSHNULL`](#instr-null). | `18` |
-| **`6E`** | `DICTEMPTY` | _`D - ?`_ | Checks whether dictionary `D` is empty, and returns `-1` or `0` accordingly. It is an alternative mnemonics for [`ISNULL`](#instr-isnull). | `18` |
-### 10.2 Dictionary serialization and deserialization
-| xxxxxxx Opcode | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description | xxxx Gas |
-|:-|:-|:-|:-|:-|
-| **`CE`** | `STDICTS` `` | _`s b - b'`_ | Stores a _Slice_-represented dictionary `s` into _Builder_ `b`. It is actually a synonym for [`STSLICE`](#instr-stslice). | `18` |
-| **`F400`** | `STDICT` `STOPTREF` | _`D b - b'`_ | Stores dictionary `D` into _Builder_ `b`, returing the resulting _Builder_ `b'`. In other words, if `D` is a cell, performs [`STONE`](#instr-stone) and [`STREF`](#instr-stref); if `D` is _Null_, performs [`NIP`](#instr-nip) and [`STZERO`](#instr-stzero); otherwise throws a type checking exception. | `26` |
-| **`F401`** | `SKIPDICT` `SKIPOPTREF` | _`s - s'`_ | Equivalent to [`LDDICT`](#instr-lddict) [`NIP`](#instr-nip). | `26` |
-| **`F402`** | `LDDICTS` | _`s - s' s''`_ | Loads (parses) a (_Slice_-represented) dictionary `s'` from _Slice_ `s`, and returns the remainder of `s` as `s''`. This is a “split function'' for all `HashmapE(n,X)` dictionary types. | `26` |
-| **`F403`** | `PLDDICTS` | _`s - s'`_ | Preloads a (_Slice_-represented) dictionary `s'` from _Slice_ `s`. Approximately equivalent to [`LDDICTS`](#instr-lddicts) [`DROP`](#instr-drop). | `26` |
-| **`F404`** | `LDDICT` `LDOPTREF` | _`s - D s'`_ | Loads (parses) a dictionary `D` from _Slice_ `s`, and returns the remainder of `s` as `s'`. May be applied to dictionaries or to values of arbitrary `(^Y)?` types. | `26` |
-| **`F405`** | `PLDDICT` `PLDOPTREF` | _`s - D`_ | Preloads a dictionary `D` from _Slice_ `s`. Approximately equivalent to [`LDDICT`](#instr-lddict) [`DROP`](#instr-drop). | `26` |
-| **`F406`** | `LDDICTQ` | _`s - D s' -1 or s 0`_ | A quiet version of [`LDDICT`](#instr-lddict). | `26` |
-| **`F407`** | `PLDDICTQ` | _`s - D -1 or 0`_ | A quiet version of [`PLDDICT`](#instr-plddict). | `26` |
-### 10.3 Get dictionary operations
-| xxxxxxx Opcode | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description | xxxx Gas |
-|:-|:-|:-|:-|:-|
-| **`F40A`** | `DICTGET` | _`k D n - x -1 or 0`_ | Looks up key `k` (represented by a _Slice_, the first `0 <= n <= 1023` data bits of which are used as a key) in dictionary `D` of type `HashmapE(n,X)` with `n`-bit keys. On success, returns the value found as a _Slice_ `x`. | |
-| **`F40B`** | `DICTGETREF` | _`k D n - c -1 or 0`_ | Similar to [`DICTGET`](#instr-dictget), but with a [`LDREF`](#instr-ldref) [`ENDS`](#instr-ends) applied to `x` on success. This operation is useful for dictionaries of type `HashmapE(n,^Y)`. | |
-| **`F40C`** | `DICTIGET` | _`i D n - x -1 or 0`_ | Similar to [`DICTGET`](#instr-dictget), but with a signed (big-endian) `n`-bit _Integer_ `i` as a key. If `i` does not fit into `n` bits, returns `0`. If `i` is a `NaN`, throws an integer overflow exception. | |
-| **`F40D`** | `DICTIGETREF` | _`i D n - c -1 or 0`_ | Combines [`DICTIGET`](#instr-dictiget) with [`DICTGETREF`](#instr-dictgetref): it uses signed `n`-bit _Integer_ `i` as a key and returns a _Cell_ instead of a _Slice_ on success. | |
-| **`F40E`** | `DICTUGET` | _`i D n - x -1 or 0`_ | Similar to [`DICTIGET`](#instr-dictiget), but with _unsigned_ (big-endian) `n`-bit _Integer_ `i` used as a key. | |
-| **`F40F`** | `DICTUGETREF` | _`i D n - c -1 or 0`_ | Similar to [`DICTIGETREF`](#instr-dictigetref), but with an unsigned `n`-bit _Integer_ key `i`. | |
-### 10.4 Set/Replace/Add dictionary operations
-| xxxxxxx Opcode | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description | xxxx Gas |
-|:-|:-|:-|:-|:-|
-| **`F412`** | `DICTSET` | _`x k D n - D'`_ | Sets the value associated with `n`-bit key `k` (represented by a _Slice_ as in [`DICTGET`](#instr-dictget)) in dictionary `D` (also represented by a _Slice_) to value `x` (again a _Slice_), and returns the resulting dictionary as `D'`. | |
-| **`F413`** | `DICTSETREF` | _`c k D n - D'`_ | Similar to [`DICTSET`](#instr-dictset), but with the value set to a reference to _Cell_ `c`. | |
-| **`F414`** | `DICTISET` | _`x i D n - D'`_ | Similar to [`DICTSET`](#instr-dictset), but with the key represented by a (big-endian) signed `n`-bit integer `i`. If `i` does not fit into `n` bits, a range check exception is generated. | |
-| **`F415`** | `DICTISETREF` | _`c i D n - D'`_ | Similar to [`DICTSETREF`](#instr-dictsetref), but with the key a signed `n`-bit integer as in [`DICTISET`](#instr-dictiset). | |
-| **`F416`** | `DICTUSET` | _`x i D n - D'`_ | Similar to [`DICTISET`](#instr-dictiset), but with `i` an _unsigned_ `n`-bit integer. | |
-| **`F417`** | `DICTUSETREF` | _`c i D n - D'`_ | Similar to [`DICTISETREF`](#instr-dictisetref), but with `i` unsigned. | |
-| **`F41A`** | `DICTSETGET` | _`x k D n - D' y -1 or D' 0`_ | Combines [`DICTSET`](#instr-dictset) with [`DICTGET`](#instr-dictget): it sets the value corresponding to key `k` to `x`, but also returns the old value `y` associated with the key in question, if present. | |
-| **`F41B`** | `DICTSETGETREF` | _`c k D n - D' c' -1 or D' 0`_ | Combines [`DICTSETREF`](#instr-dictsetref) with [`DICTGETREF`](#instr-dictgetref) similarly to [`DICTSETGET`](#instr-dictsetget). | |
-| **`F41C`** | `DICTISETGET` | _`x i D n - D' y -1 or D' 0`_ | [`DICTISETGET`](#instr-dictisetget), but with `i` a signed `n`-bit integer. | |
-| **`F41D`** | `DICTISETGETREF` | _`c i D n - D' c' -1 or D' 0`_ | [`DICTISETGETREF`](#instr-dictisetgetref), but with `i` a signed `n`-bit integer. | |
-| **`F41E`** | `DICTUSETGET` | _`x i D n - D' y -1 or D' 0`_ | [`DICTISETGET`](#instr-dictisetget), but with `i` an unsigned `n`-bit integer. | |
-| **`F41F`** | `DICTUSETGETREF` | _`c i D n - D' c' -1 or D' 0`_ | [`DICTISETGETREF`](#instr-dictisetgetref), but with `i` an unsigned `n`-bit integer. | |
-| **`F422`** | `DICTREPLACE` | _`x k D n - D' -1 or D 0`_ | A _Replace_ operation, which is similar to [`DICTSET`](#instr-dictset), but sets the value of key `k` in dictionary `D` to `x` only if the key `k` was already present in `D`. | |
-| **`F423`** | `DICTREPLACEREF` | _`c k D n - D' -1 or D 0`_ | A _Replace_ counterpart of [`DICTSETREF`](#instr-dictsetref). | |
-| **`F424`** | `DICTIREPLACE` | _`x i D n - D' -1 or D 0`_ | [`DICTREPLACE`](#instr-dictreplace), but with `i` a signed `n`-bit integer. | |
-| **`F425`** | `DICTIREPLACEREF` | _`c i D n - D' -1 or D 0`_ | [`DICTREPLACEREF`](#instr-dictreplaceref), but with `i` a signed `n`-bit integer. | |
-| **`F426`** | `DICTUREPLACE` | _`x i D n - D' -1 or D 0`_ | [`DICTREPLACE`](#instr-dictreplace), but with `i` an unsigned `n`-bit integer. | |
-| **`F427`** | `DICTUREPLACEREF` | _`c i D n - D' -1 or D 0`_ | [`DICTREPLACEREF`](#instr-dictreplaceref), but with `i` an unsigned `n`-bit integer. | |
-| **`F42A`** | `DICTREPLACEGET` | _`x k D n - D' y -1 or D 0`_ | A _Replace_ counterpart of [`DICTSETGET`](#instr-dictsetget): on success, also returns the old value associated with the key in question. | |
-| **`F42B`** | `DICTREPLACEGETREF` | _`c k D n - D' c' -1 or D 0`_ | A _Replace_ counterpart of [`DICTSETGETREF`](#instr-dictsetgetref). | |
-| **`F42C`** | `DICTIREPLACEGET` | _`x i D n - D' y -1 or D 0`_ | [`DICTREPLACEGET`](#instr-dictreplaceget), but with `i` a signed `n`-bit integer. | |
-| **`F42D`** | `DICTIREPLACEGETREF` | _`c i D n - D' c' -1 or D 0`_ | [`DICTREPLACEGETREF`](#instr-dictreplacegetref), but with `i` a signed `n`-bit integer. | |
-| **`F42E`** | `DICTUREPLACEGET` | _`x i D n - D' y -1 or D 0`_ | [`DICTREPLACEGET`](#instr-dictreplaceget), but with `i` an unsigned `n`-bit integer. | |
-| **`F42F`** | `DICTUREPLACEGETREF` | _`c i D n - D' c' -1 or D 0`_ | [`DICTREPLACEGETREF`](#instr-dictreplacegetref), but with `i` an unsigned `n`-bit integer. | |
-| **`F432`** | `DICTADD` | _`x k D n - D' -1 or D 0`_ | An _Add_ counterpart of [`DICTSET`](#instr-dictset): sets the value associated with key `k` in dictionary `D` to `x`, but only if it is not already present in `D`. | |
-| **`F433`** | `DICTADDREF` | _`c k D n - D' -1 or D 0`_ | An _Add_ counterpart of [`DICTSETREF`](#instr-dictsetref). | |
-| **`F434`** | `DICTIADD` | _`x i D n - D' -1 or D 0`_ | [`DICTADD`](#instr-dictadd), but with `i` a signed `n`-bit integer. | |
-| **`F435`** | `DICTIADDREF` | _`c i D n - D' -1 or D 0`_ | [`DICTADDREF`](#instr-dictaddref), but with `i` a signed `n`-bit integer. | |
-| **`F436`** | `DICTUADD` | _`x i D n - D' -1 or D 0`_ | [`DICTADD`](#instr-dictadd), but with `i` an unsigned `n`-bit integer. | |
-| **`F437`** | `DICTUADDREF` | _`c i D n - D' -1 or D 0`_ | [`DICTADDREF`](#instr-dictaddref), but with `i` an unsigned `n`-bit integer. | |
-| **`F43A`** | `DICTADDGET` | _`x k D n - D' -1 or D y 0`_ | An _Add_ counterpart of [`DICTSETGET`](#instr-dictsetget): sets the value associated with key `k` in dictionary `D` to `x`, but only if key `k` is not already present in `D`. Otherwise, just returns the old value `y` without changing the dictionary. | |
-| **`F43B`** | `DICTADDGETREF` | _`c k D n - D' -1 or D c' 0`_ | An _Add_ counterpart of [`DICTSETGETREF`](#instr-dictsetgetref). | |
-| **`F43C`** | `DICTIADDGET` | _`x i D n - D' -1 or D y 0`_ | [`DICTADDGET`](#instr-dictaddget), but with `i` a signed `n`-bit integer. | |
-| **`F43D`** | `DICTIADDGETREF` | _`c i D n - D' -1 or D c' 0`_ | [`DICTADDGETREF`](#instr-dictaddgetref), but with `i` a signed `n`-bit integer. | |
-| **`F43E`** | `DICTUADDGET` | _`x i D n - D' -1 or D y 0`_ | [`DICTADDGET`](#instr-dictaddget), but with `i` an unsigned `n`-bit integer. | |
-| **`F43F`** | `DICTUADDGETREF` | _`c i D n - D' -1 or D c' 0`_ | [`DICTADDGETREF`](#instr-dictaddgetref), but with `i` an unsigned `n`-bit integer. | |
-### 10.5 Builder-accepting variants of Set dictionary operations
-The following primitives accept the new value as a _Builder_ `b` instead of a _Slice_ `x`.
-
-| xxxxxxx Opcode | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description | xxxx Gas |
-|:-|:-|:-|:-|:-|
-| **`F441`** | `DICTSETB` | _`b k D n - D'`_ | | |
-| **`F442`** | `DICTISETB` | _`b i D n - D'`_ | | |
-| **`F443`** | `DICTUSETB` | _`b i D n - D'`_ | | |
-| **`F445`** | `DICTSETGETB` | _`b k D n - D' y -1 or D' 0`_ | | |
-| **`F446`** | `DICTISETGETB` | _`b i D n - D' y -1 or D' 0`_ | | |
-| **`F447`** | `DICTUSETGETB` | _`b i D n - D' y -1 or D' 0`_ | | |
-| **`F449`** | `DICTREPLACEB` | _`b k D n - D' -1 or D 0`_ | | |
-| **`F44A`** | `DICTIREPLACEB` | _`b i D n - D' -1 or D 0`_ | | |
-| **`F44B`** | `DICTUREPLACEB` | _`b i D n - D' -1 or D 0`_ | | |
-| **`F44D`** | `DICTREPLACEGETB` | _`b k D n - D' y -1 or D 0`_ | | |
-| **`F44E`** | `DICTIREPLACEGETB` | _`b i D n - D' y -1 or D 0`_ | | |
-| **`F44F`** | `DICTUREPLACEGETB` | _`b i D n - D' y -1 or D 0`_ | | |
-| **`F451`** | `DICTADDB` | _`b k D n - D' -1 or D 0`_ | | |
-| **`F452`** | `DICTIADDB` | _`b i D n - D' -1 or D 0`_ | | |
-| **`F453`** | `DICTUADDB` | _`b i D n - D' -1 or D 0`_ | | |
-| **`F455`** | `DICTADDGETB` | _`b k D n - D' -1 or D y 0`_ | | |
-| **`F456`** | `DICTIADDGETB` | _`b i D n - D' -1 or D y 0`_ | | |
-| **`F457`** | `DICTUADDGETB` | _`b i D n - D' -1 or D y 0`_ | | |
-### 10.6 Delete dictionary operations
-| xxxxxxx Opcode | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description | xxxx Gas |
-|:-|:-|:-|:-|:-|
-| **`F459`** | `DICTDEL` | _`k D n - D' -1 or D 0`_ | Deletes `n`-bit key, represented by a _Slice_ `k`, from dictionary `D`. If the key is present, returns the modified dictionary `D'` and the success flag `-1`. Otherwise, returns the original dictionary `D` and `0`. | |
-| **`F45A`** | `DICTIDEL` | _`i D n - D' ?`_ | A version of [`DICTDEL`](#instr-dictdel) with the key represented by a signed `n`-bit _Integer_ `i`. If `i` does not fit into `n` bits, simply returns `D` `0` (“key not found, dictionary unmodified''). | |
-| **`F45B`** | `DICTUDEL` | _`i D n - D' ?`_ | Similar to [`DICTIDEL`](#instr-dictidel), but with `i` an unsigned `n`-bit integer. | |
-| **`F462`** | `DICTDELGET` | _`k D n - D' x -1 or D 0`_ | Deletes `n`-bit key, represented by a _Slice_ `k`, from dictionary `D`. If the key is present, returns the modified dictionary `D'`, the original value `x` associated with the key `k` (represented by a _Slice_), and the success flag `-1`. Otherwise, returns the original dictionary `D` and `0`. | |
-| **`F463`** | `DICTDELGETREF` | _`k D n - D' c -1 or D 0`_ | Similar to [`DICTDELGET`](#instr-dictdelget), but with [`LDREF`](#instr-ldref) [`ENDS`](#instr-ends) applied to `x` on success, so that the value returned `c` is a _Cell_. | |
-| **`F464`** | `DICTIDELGET` | _`i D n - D' x -1 or D 0`_ | [`DICTDELGET`](#instr-dictdelget), but with `i` a signed `n`-bit integer. | |
-| **`F465`** | `DICTIDELGETREF` | _`i D n - D' c -1 or D 0`_ | [`DICTDELGETREF`](#instr-dictdelgetref), but with `i` a signed `n`-bit integer. | |
-| **`F466`** | `DICTUDELGET` | _`i D n - D' x -1 or D 0`_ | [`DICTDELGET`](#instr-dictdelget), but with `i` an unsigned `n`-bit integer. | |
-| **`F467`** | `DICTUDELGETREF` | _`i D n - D' c -1 or D 0`_ | [`DICTDELGETREF`](#instr-dictdelgetref), but with `i` an unsigned `n`-bit integer. | |
-### 10.7 "Maybe reference" dictionary operations
-The following operations assume that a dictionary is used to store values `c?` of type _Maybe Cell_. The representation is as follows: if `c?` is a _Cell_ , it is stored as a value with no data bits and exactly one reference to this _Cell_. If `c?` is _Null_, then the corresponding key must be absent from the dictionary.
-
-| xxxxxxx Opcode | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description | xxxx Gas |
-|:-|:-|:-|:-|:-|
-| **`F469`** | `DICTGETOPTREF` | _`k D n - c^?`_ | A variant of [`DICTGETREF`](#instr-dictgetref) that returns _Null_ instead of the value `c^?` if the key `k` is absent from dictionary `D`. | |
-| **`F46A`** | `DICTIGETOPTREF` | _`i D n - c^?`_ | [`DICTGETOPTREF`](#instr-dictgetoptref), but with `i` a signed `n`-bit integer. If the key `i` is out of range, also returns _Null_. | |
-| **`F46B`** | `DICTUGETOPTREF` | _`i D n - c^?`_ | [`DICTGETOPTREF`](#instr-dictgetoptref), but with `i` an unsigned `n`-bit integer. If the key `i` is out of range, also returns _Null_. | |
-| **`F46D`** | `DICTSETGETOPTREF` | _`c^? k D n - D' ~c^?`_ | A variant of both [`DICTGETOPTREF`](#instr-dictgetoptref) and [`DICTSETGETREF`](#instr-dictsetgetref) that sets the value corresponding to key `k` in dictionary `D` to `c^?` (if `c^?` is _Null_, then the key is deleted instead), and returns the old value `~c^?` (if the key `k` was absent before, returns _Null_ instead). | |
-| **`F46E`** | `DICTISETGETOPTREF` | _`c^? i D n - D' ~c^?`_ | Similar to primitive [`DICTSETGETOPTREF`](#instr-dictsetgetoptref), but using signed `n`-bit _Integer_ `i` as a key. If `i` does not fit into `n` bits, throws a range checking exception. | |
-| **`F46F`** | `DICTUSETGETOPTREF` | _`c^? i D n - D' ~c^?`_ | Similar to primitive [`DICTSETGETOPTREF`](#instr-dictsetgetoptref), but using unsigned `n`-bit _Integer_ `i` as a key. | |
-### 10.8 Prefix code dictionary operations
-These are some basic operations for constructing prefix code dictionaries.
-These primitives are completely similar to their non-prefix code counterparts ([`DICTSET`](#instr-dictset) etc), with the obvious difference that even a _Set_ may fail in a prefix code dictionary, so a success flag must be returned by [`PFXDICTSET`](#instr-pfxdictset) as well.
-
-| xxxxxxx Opcode | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description | xxxx Gas |
-|:-|:-|:-|:-|:-|
-| **`F470`** | `PFXDICTSET` | _`x k D n - D' -1 or D 0`_ | | |
-| **`F471`** | `PFXDICTREPLACE` | _`x k D n - D' -1 or D 0`_ | | |
-| **`F472`** | `PFXDICTADD` | _`x k D n - D' -1 or D 0`_ | | |
-| **`F473`** | `PFXDICTDEL` | _`k D n - D' -1 or D 0`_ | | |
-### 10.9 Variants of GetNext and GetPrev operations
-| xxxxxxx Opcode | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description | xxxx Gas |
-|:-|:-|:-|:-|:-|
-| **`F474`** | `DICTGETNEXT` | _`k D n - x' k' -1 or 0`_ | Computes the minimal key `k'` in dictionary `D` that is lexicographically greater than `k`, and returns `k'` (represented by a _Slice_) along with associated value `x'` (also represented by a _Slice_). | |
-| **`F475`** | `DICTGETNEXTEQ` | _`k D n - x' k' -1 or 0`_ | Similar to [`DICTGETNEXT`](#instr-dictgetnext), but computes the minimal key `k'` that is lexicographically greater than or equal to `k`. | |
-| **`F476`** | `DICTGETPREV` | _`k D n - x' k' -1 or 0`_ | Similar to [`DICTGETNEXT`](#instr-dictgetnext), but computes the maximal key `k'` lexicographically smaller than `k`. | |
-| **`F477`** | `DICTGETPREVEQ` | _`k D n - x' k' -1 or 0`_ | Similar to [`DICTGETPREV`](#instr-dictgetprev), but computes the maximal key `k'` lexicographically smaller than or equal to `k`. | |
-| **`F478`** | `DICTIGETNEXT` | _`i D n - x' i' -1 or 0`_ | Similar to [`DICTGETNEXT`](#instr-dictgetnext), but interprets all keys in dictionary `D` as big-endian signed `n`-bit integers, and computes the minimal key `i'` that is larger than _Integer_ `i` (which does not necessarily fit into `n` bits). | |
-| **`F479`** | `DICTIGETNEXTEQ` | _`i D n - x' i' -1 or 0`_ | Similar to [`DICTGETNEXTEQ`](#instr-dictgetnexteq), but interprets keys as signed `n`-bit integers. | |
-| **`F47A`** | `DICTIGETPREV` | _`i D n - x' i' -1 or 0`_ | Similar to [`DICTGETPREV`](#instr-dictgetprev), but interprets keys as signed `n`-bit integers. | |
-| **`F47B`** | `DICTIGETPREVEQ` | _`i D n - x' i' -1 or 0`_ | Similar to [`DICTGETPREVEQ`](#instr-dictgetpreveq), but interprets keys as signed `n`-bit integers. | |
-| **`F47C`** | `DICTUGETNEXT` | _`i D n - x' i' -1 or 0`_ | Similar to [`DICTGETNEXT`](#instr-dictgetnext), but interprets all keys in dictionary `D` as big-endian unsigned `n`-bit integers, and computes the minimal key `i'` that is larger than _Integer_ `i` (which does not necessarily fit into `n` bits, and is not necessarily non-negative). | |
-| **`F47D`** | `DICTUGETNEXTEQ` | _`i D n - x' i' -1 or 0`_ | Similar to [`DICTGETNEXTEQ`](#instr-dictgetnexteq), but interprets keys as unsigned `n`-bit integers. | |
-| **`F47E`** | `DICTUGETPREV` | _`i D n - x' i' -1 or 0`_ | Similar to [`DICTGETPREV`](#instr-dictgetprev), but interprets keys as unsigned `n`-bit integers. | |
-| **`F47F`** | `DICTUGETPREVEQ` | _`i D n - x' i' -1 or 0`_ | Similar to [`DICTGETPREVEQ`](#instr-dictgetpreveq), but interprets keys a unsigned `n`-bit integers. | |
-### 10.10 GetMin, GetMax, RemoveMin, RemoveMax operations
-| xxxxxxx Opcode | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description | xxxx Gas |
-|:-|:-|:-|:-|:-|
-| **`F482`** | `DICTMIN` | _`D n - x k -1 or 0`_ | Computes the minimal key `k` (represented by a _Slice_ with `n` data bits) in dictionary `D`, and returns `k` along with the associated value `x`. | |
-| **`F483`** | `DICTMINREF` | _`D n - c k -1 or 0`_ | Similar to [`DICTMIN`](#instr-dictmin), but returns the only reference in the value as a _Cell_ `c`. | |
-| **`F484`** | `DICTIMIN` | _`D n - x i -1 or 0`_ | Similar to [`DICTMIN`](#instr-dictmin), but computes the minimal key `i` under the assumption that all keys are big-endian signed `n`-bit integers. Notice that the key and value returned may differ from those computed by [`DICTMIN`](#instr-dictmin) and [`DICTUMIN`](#instr-dictumin). | |
-| **`F485`** | `DICTIMINREF` | _`D n - c i -1 or 0`_ | Similar to [`DICTIMIN`](#instr-dictimin), but returns the only reference in the value. | |
-| **`F486`** | `DICTUMIN` | _`D n - x i -1 or 0`_ | Similar to [`DICTMIN`](#instr-dictmin), but returns the key as an unsigned `n`-bit _Integer_ `i`. | |
-| **`F487`** | `DICTUMINREF` | _`D n - c i -1 or 0`_ | Similar to [`DICTUMIN`](#instr-dictumin), but returns the only reference in the value. | |
-| **`F48A`** | `DICTMAX` | _`D n - x k -1 or 0`_ | Computes the maximal key `k` (represented by a _Slice_ with `n` data bits) in dictionary `D`, and returns `k` along with the associated value `x`. | |
-| **`F48B`** | `DICTMAXREF` | _`D n - c k -1 or 0`_ | Similar to [`DICTMAX`](#instr-dictmax), but returns the only reference in the value. | |
-| **`F48C`** | `DICTIMAX` | _`D n - x i -1 or 0`_ | Similar to [`DICTMAX`](#instr-dictmax), but computes the maximal key `i` under the assumption that all keys are big-endian signed `n`-bit integers. Notice that the key and value returned may differ from those computed by [`DICTMAX`](#instr-dictmax) and [`DICTUMAX`](#instr-dictumax). | |
-| **`F48D`** | `DICTIMAXREF` | _`D n - c i -1 or 0`_ | Similar to [`DICTIMAX`](#instr-dictimax), but returns the only reference in the value. | |
-| **`F48E`** | `DICTUMAX` | _`D n - x i -1 or 0`_ | Similar to [`DICTMAX`](#instr-dictmax), but returns the key as an unsigned `n`-bit _Integer_ `i`. | |
-| **`F48F`** | `DICTUMAXREF` | _`D n - c i -1 or 0`_ | Similar to [`DICTUMAX`](#instr-dictumax), but returns the only reference in the value. | |
-| **`F492`** | `DICTREMMIN` | _`D n - D' x k -1 or D 0`_ | Computes the minimal key `k` (represented by a _Slice_ with `n` data bits) in dictionary `D`, removes `k` from the dictionary, and returns `k` along with the associated value `x` and the modified dictionary `D'`. | |
-| **`F493`** | `DICTREMMINREF` | _`D n - D' c k -1 or D 0`_ | Similar to [`DICTREMMIN`](#instr-dictremmin), but returns the only reference in the value as a _Cell_ `c`. | |
-| **`F494`** | `DICTIREMMIN` | _`D n - D' x i -1 or D 0`_ | Similar to [`DICTREMMIN`](#instr-dictremmin), but computes the minimal key `i` under the assumption that all keys are big-endian signed `n`-bit integers. Notice that the key and value returned may differ from those computed by [`DICTREMMIN`](#instr-dictremmin) and [`DICTUREMMIN`](#instr-dicturemmin). | |
-| **`F495`** | `DICTIREMMINREF` | _`D n - D' c i -1 or D 0`_ | Similar to [`DICTIREMMIN`](#instr-dictiremmin), but returns the only reference in the value. | |
-| **`F496`** | `DICTUREMMIN` | _`D n - D' x i -1 or D 0`_ | Similar to [`DICTREMMIN`](#instr-dictremmin), but returns the key as an unsigned `n`-bit _Integer_ `i`. | |
-| **`F497`** | `DICTUREMMINREF` | _`D n - D' c i -1 or D 0`_ | Similar to [`DICTUREMMIN`](#instr-dicturemmin), but returns the only reference in the value. | |
-| **`F49A`** | `DICTREMMAX` | _`D n - D' x k -1 or D 0`_ | Computes the maximal key `k` (represented by a _Slice_ with `n` data bits) in dictionary `D`, removes `k` from the dictionary, and returns `k` along with the associated value `x` and the modified dictionary `D'`. | |
-| **`F49B`** | `DICTREMMAXREF` | _`D n - D' c k -1 or D 0`_ | Similar to [`DICTREMMAX`](#instr-dictremmax), but returns the only reference in the value as a _Cell_ `c`. | |
-| **`F49C`** | `DICTIREMMAX` | _`D n - D' x i -1 or D 0`_ | Similar to [`DICTREMMAX`](#instr-dictremmax), but computes the minimal key `i` under the assumption that all keys are big-endian signed `n`-bit integers. Notice that the key and value returned may differ from those computed by [`DICTREMMAX`](#instr-dictremmax) and [`DICTUREMMAX`](#instr-dicturemmax). | |
-| **`F49D`** | `DICTIREMMAXREF` | _`D n - D' c i -1 or D 0`_ | Similar to [`DICTIREMMAX`](#instr-dictiremmax), but returns the only reference in the value. | |
-| **`F49E`** | `DICTUREMMAX` | _`D n - D' x i -1 or D 0`_ | Similar to [`DICTREMMAX`](#instr-dictremmax), but returns the key as an unsigned `n`-bit _Integer_ `i`. | |
-| **`F49F`** | `DICTUREMMAXREF` | _`D n - D' c i -1 or D 0`_ | Similar to [`DICTUREMMAX`](#instr-dicturemmax), but returns the only reference in the value. | |
-### 10.11 Special Get dictionary and prefix code dictionary operations and constant dictionaries
-| xxxxxxx Opcode | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description | xxxx Gas |
-|:-|:-|:-|:-|:-|
-| **`F4A0`** | `DICTIGETJMP` | _`i D n - `_ | Similar to [`DICTIGET`](#instr-dictiget), but with `x` [`BLESS`](#instr-bless)ed into a continuation with a subsequent [`JMPX`](#instr-jmpx) to it on success. On failure, does nothing. This is useful for implementing `switch`/`case` constructions. | |
-| **`F4A1`** | `DICTUGETJMP` | _`i D n - `_ | Similar to [`DICTIGETJMP`](#instr-dictigetjmp), but performs [`DICTUGET`](#instr-dictuget) instead of [`DICTIGET`](#instr-dictiget). | |
-| **`F4A2`** | `DICTIGETEXEC` | _`i D n - `_ | Similar to [`DICTIGETJMP`](#instr-dictigetjmp), but with [`EXECUTE`](#instr-execute) instead of [`JMPX`](#instr-jmpx). | |
-| **`F4A3`** | `DICTUGETEXEC` | _`i D n - `_ | Similar to [`DICTUGETJMP`](#instr-dictugetjmp), but with [`EXECUTE`](#instr-execute) instead of [`JMPX`](#instr-jmpx). | |
-| **`F4A6_n`** | `[ref] [n] DICTPUSHCONST` | _` - D n`_ | Pushes a non-empty constant dictionary `D` (as a `Cell^?`) along with its key length `0 <= n <= 1023`, stored as a part of the instruction. The dictionary itself is created from the first of remaining references of the current continuation. In this way, the complete [`DICTPUSHCONST`](#instr-dictpushconst) instruction can be obtained by first serializing `xF4A4_`, then the non-empty dictionary itself (one `1` bit and a cell reference), and then the unsigned 10-bit integer `n` (as if by a `STU 10` instruction). An empty dictionary can be pushed by a [`NEWDICT`](#instr-newdict) primitive instead. | `34` |
-| **`F4A8`** | `PFXDICTGETQ` | _`s D n - s' x s'' -1 or s 0`_ | Looks up the unique prefix of _Slice_ `s` present in the prefix code dictionary represented by `Cell^?` `D` and `0 <= n <= 1023`. If found, the prefix of `s` is returned as `s'`, and the corresponding value (also a _Slice_) as `x`. The remainder of `s` is returned as a _Slice_ `s''`. If no prefix of `s` is a key in prefix code dictionary `D`, returns the unchanged `s` and a zero flag to indicate failure. | |
-| **`F4A9`** | `PFXDICTGET` | _`s D n - s' x s''`_ | Similar to [`PFXDICTGET`](#instr-pfxdictget), but throws a cell deserialization failure exception on failure. | |
-| **`F4AA`** | `PFXDICTGETJMP` | _`s D n - s' s'' or s`_ | Similar to [`PFXDICTGETQ`](#instr-pfxdictgetq), but on success [`BLESS`](#instr-bless)es the value `x` into a _Continuation_ and transfers control to it as if by a [`JMPX`](#instr-jmpx). On failure, returns `s` unchanged and continues execution. | |
-| **`F4AB`** | `PFXDICTGETEXEC` | _`s D n - s' s''`_ | Similar to [`PFXDICTGETJMP`](#instr-pfxdictgetjmp), but `EXEC`utes the continuation found instead of jumping to it. On failure, throws a cell deserialization exception. | |
-| **`F4AE_n`** | `[ref] [n] PFXDICTCONSTGETJMP` `[ref] [n] PFXDICTSWITCH` | _`s - s' s'' or s`_ | Combines [`[n] DICTPUSHCONST`](#instr-dictpushconst) for `0 <= n <= 1023` with [`PFXDICTGETJMP`](#instr-pfxdictgetjmp). | |
-| **`F4BC`** | `DICTIGETJMPZ` | _`i D n - i or nothing`_ | A variant of [`DICTIGETJMP`](#instr-dictigetjmp) that returns index `i` on failure. | |
-| **`F4BD`** | `DICTUGETJMPZ` | _`i D n - i or nothing`_ | A variant of [`DICTUGETJMP`](#instr-dictugetjmp) that returns index `i` on failure. | |
-| **`F4BE`** | `DICTIGETEXECZ` | _`i D n - i or nothing`_ | A variant of [`DICTIGETEXEC`](#instr-dictigetexec) that returns index `i` on failure. | |
-| **`F4BF`** | `DICTUGETEXECZ` | _`i D n - i or nothing`_ | A variant of [`DICTUGETEXEC`](#instr-dictugetexec) that returns index `i` on failure. | |
-### 10.12 SubDict dictionary operations
-| xxxxxxx Opcode | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description | xxxx Gas |
-|:-|:-|:-|:-|:-|
-| **`F4B1`** | `SUBDICTGET` | _`k l D n - D'`_ | Constructs a subdictionary consisting of all keys beginning with prefix `k` (represented by a _Slice_, the first `0 <= l <= n <= 1023` data bits of which are used as a key) of length `l` in dictionary `D` of type `HashmapE(n,X)` with `n`-bit keys. On success, returns the new subdictionary of the same type `HashmapE(n,X)` as a _Slice_ `D'`. | |
-| **`F4B2`** | `SUBDICTIGET` | _`x l D n - D'`_ | Variant of [`SUBDICTGET`](#instr-subdictget) with the prefix represented by a signed big-endian `l`-bit _Integer_ `x`, where necessarily `l <= 257`. | |
-| **`F4B3`** | `SUBDICTUGET` | _`x l D n - D'`_ | Variant of [`SUBDICTGET`](#instr-subdictget) with the prefix represented by an unsigned big-endian `l`-bit _Integer_ `x`, where necessarily `l <= 256`. | |
-| **`F4B5`** | `SUBDICTRPGET` | _`k l D n - D'`_ | Similar to [`SUBDICTGET`](#instr-subdictget), but removes the common prefix `k` from all keys of the new dictionary `D'`, which becomes of type `HashmapE(n-l,X)`. | |
-| **`F4B6`** | `SUBDICTIRPGET` | _`x l D n - D'`_ | Variant of [`SUBDICTRPGET`](#instr-subdictrpget) with the prefix represented by a signed big-endian `l`-bit _Integer_ `x`, where necessarily `l <= 257`. | |
-| **`F4B7`** | `SUBDICTURPGET` | _`x l D n - D'`_ | Variant of [`SUBDICTRPGET`](#instr-subdictrpget) with the prefix represented by an unsigned big-endian `l`-bit _Integer_ `x`, where necessarily `l <= 256`. | |
-
-## 11 Application-specific primitives
-### 11.1 Gas-related primitives
-| xxxxxxx Opcode | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description | xxxx Gas |
-|:-|:-|:-|:-|:-|
-| **`F800`** | `ACCEPT` | _`-`_ | Sets current gas limit `g_l` to its maximal allowed value `g_m`, and resets the gas credit `g_c` to zero, decreasing the value of `g_r` by `g_c` in the process. In other words, the current smart contract agrees to buy some gas to finish the current transaction. This action is required to process external messages, which bring no value (hence no gas) with themselves. | `26` |
-| **`F801`** | `SETGASLIMIT` | _`g - `_ | Sets current gas limit `g_l` to the minimum of `g` and `g_m`, and resets the gas credit `g_c` to zero. If the gas consumed so far (including the present instruction) exceeds the resulting value of `g_l`, an (unhandled) out of gas exception is thrown before setting new gas limits. Notice that [`SETGASLIMIT`](#instr-setgaslimit) with an argument `g >= 2^63-1` is equivalent to [`ACCEPT`](#instr-accept). | `26` |
-| **`F80F`** | `COMMIT` | _`-`_ | Commits the current state of registers `c4` (“persistent data'') and `c5` (“actions'') so that the current execution is considered “successful'' with the saved values even if an exception is thrown later. | `26` |
-### 11.2 Pseudo-random number generator primitives
-| xxxxxxx Opcode | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description | xxxx Gas |
-|:-|:-|:-|:-|:-|
-| **`F810`** | `RANDU256` | _`- x`_ | Generates a new pseudo-random unsigned 256-bit _Integer_ `x`. The algorithm is as follows: if `r` is the old value of the random seed, considered as a 32-byte array (by constructing the big-endian representation of an unsigned 256-bit integer), then its `sha512(r)` is computed; the first 32 bytes of this hash are stored as the new value `r'` of the random seed, and the remaining 32 bytes are returned as the next random value `x`. | `26+\|c7\|+\|c1_1\|` |
-| **`F811`** | `RAND` | _`y - z`_ | Generates a new pseudo-random integer `z` in the range `0...y-1` (or `y...-1`, if `y<0`). More precisely, an unsigned random value `x` is generated as in `RAND256U`; then `z:=floor(x*y/2^256)` is computed. Equivalent to [`RANDU256`](#instr-randu256) [`256 MULRSHIFT`](#instr-mulrshift-var). | `26+\|c7\|+\|c1_1\|` |
-| **`F814`** | `SETRAND` | _`x - `_ | Sets the random seed to unsigned 256-bit _Integer_ `x`. | `26+\|c7\|+\|c1_1\|` |
-| **`F815`** | `ADDRAND` `RANDOMIZE` | _`x - `_ | Mixes unsigned 256-bit _Integer_ `x` into the random seed `r` by setting the random seed to `Sha` of the concatenation of two 32-byte strings: the first with the big-endian representation of the old seed `r`, and the second with the big-endian representation of `x`. | `26` |
-### 11.3 Configuration primitives
-| xxxxxxx Opcode | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description | xxxx Gas |
-|:-|:-|:-|:-|:-|
-| **`F82i`** | `[i] GETPARAM` | _` - x`_ | Returns the `i`-th parameter from the _Tuple_ provided at `c7` for `0 <= i <= 15`. Equivalent to [`c7 PUSHCTR`](#instr-pushctr) [`FIRST`](#instr-first) [`[i] INDEX`](#instr-index). If one of these internal operations fails, throws an appropriate type checking or range checking exception. | `26` |
-| **`F823`** | `NOW` | _` - x`_ | Returns the current Unix time as an _Integer_. If it is impossible to recover the requested value starting from `c7`, throws a type checking or range checking exception as appropriate. Equivalent to [`3 GETPARAM`](#instr-getparam). | `26` |
-| **`F824`** | `BLOCKLT` | _` - x`_ | Returns the starting logical time of the current block. Equivalent to [`4 GETPARAM`](#instr-getparam). | `26` |
-| **`F825`** | `LTIME` | _` - x`_ | Returns the logical time of the current transaction. Equivalent to [`5 GETPARAM`](#instr-getparam). | `26` |
-| **`F826`** | `RANDSEED` | _` - x`_ | Returns the current random seed as an unsigned 256-bit _Integer_. Equivalent to [`6 GETPARAM`](#instr-getparam). | `26` |
-| **`F827`** | `BALANCE` | _` - t`_ | Returns the remaining balance of the smart contract as a _Tuple_ consisting of an _Integer_ (the remaining Gram balance in nanograms) and a _Maybe Cell_ (a dictionary with 32-bit keys representing the balance of “extra currencies''). Equivalent to [`7 GETPARAM`](#instr-getparam). Note that `RAW` primitives such as [`SENDRAWMSG`](#instr-sendrawmsg) do not update this field. | `26` |
-| **`F828`** | `MYADDR` | _` - s`_ | Returns the internal address of the current smart contract as a _Slice_ with a `MsgAddressInt`. If necessary, it can be parsed further using primitives such as [`PARSEMSGADDR`](#instr-parsemsgaddr) or [`REWRITESTDADDR`](#instr-rewritestdaddr). Equivalent to [`8 GETPARAM`](#instr-getparam). | `26` |
-| **`F829`** | `CONFIGROOT` | _` - D`_ | Returns the _Maybe Cell_ `D` with the current global configuration dictionary. Equivalent to `9 GETPARAM `. | `26` |
-| **`F830`** | `CONFIGDICT` | _` - D 32`_ | Returns the global configuration dictionary along with its key length (32). Equivalent to [`CONFIGROOT`](#instr-configroot) [`32 PUSHINT`](#instr-pushint-4). | `26` |
-| **`F832`** | `CONFIGPARAM` | _`i - c -1 or 0`_ | Returns the value of the global configuration parameter with integer index `i` as a _Cell_ `c`, and a flag to indicate success. Equivalent to [`CONFIGDICT`](#instr-configdict) [`DICTIGETREF`](#instr-dictigetref). | |
-| **`F833`** | `CONFIGOPTPARAM` | _`i - c^?`_ | Returns the value of the global configuration parameter with integer index `i` as a _Maybe Cell_ `c^?`. Equivalent to [`CONFIGDICT`](#instr-configdict) [`DICTIGETOPTREF`](#instr-dictigetoptref). | |
-### 11.4 Global variable primitives
-| xxxxxxx Opcode | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description | xxxx Gas |
-|:-|:-|:-|:-|:-|
-| **`F840`** | `GETGLOBVAR` | _`k - x`_ | Returns the `k`-th global variable for `0 <= k < 255`. Equivalent to [`c7 PUSHCTR`](#instr-pushctr) [`SWAP`](#instr-swap) [`INDEXVARQ`](#instr-indexvarq). | `26` |
-| **`F85_k`** | `[k] GETGLOB` | _` - x`_ | Returns the `k`-th global variable for `1 <= k <= 31`. Equivalent to [`c7 PUSHCTR`](#instr-pushctr) [`[k] INDEXQ`](#instr-indexq). | `26` |
-| **`F860`** | `SETGLOBVAR` | _`x k - `_ | Assigns `x` to the `k`-th global variable for `0 <= k < 255`. Equivalent to [`c7 PUSHCTR`](#instr-pushctr) [`ROTREV`](#instr-rotrev) [`SETINDEXVARQ`](#instr-setindexvarq) [`c7 POPCTR`](#instr-popctr). | `26+\|c7’\|` |
-| **`F87_k`** | `[k] SETGLOB` | _`x - `_ | Assigns `x` to the `k`-th global variable for `1 <= k <= 31`. Equivalent to [`c7 PUSHCTR`](#instr-pushctr) [`SWAP`](#instr-swap) [`k SETINDEXQ`](#instr-setindexq) [`c7 POPCTR`](#instr-popctr). | `26+\|c7’\|` |
-### 11.5 Hashing and cryptography primitives
-| xxxxxxx Opcode | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description | xxxx Gas |
-|:-|:-|:-|:-|:-|
-| **`F900`** | `HASHCU` | _`c - x`_ | Computes the representation hash of a _Cell_ `c` and returns it as a 256-bit unsigned integer `x`. Useful for signing and checking signatures of arbitrary entities represented by a tree of cells. | `26` |
-| **`F901`** | `HASHSU` | _`s - x`_ | Computes the hash of a _Slice_ `s` and returns it as a 256-bit unsigned integer `x`. The result is the same as if an ordinary cell containing only data and references from `s` had been created and its hash computed by [`HASHCU`](#instr-hashcu). | `526` |
-| **`F902`** | `SHA256U` | _`s - x`_ | Computes `Sha` of the data bits of _Slice_ `s`. If the bit length of `s` is not divisible by eight, throws a cell underflow exception. The hash value is returned as a 256-bit unsigned integer `x`. | `26` |
-| **`F910`** | `CHKSIGNU` | _`h s k - ?`_ | Checks the Ed25519-signature `s` of a hash `h` (a 256-bit unsigned integer, usually computed as the hash of some data) using public key `k` (also represented by a 256-bit unsigned integer). The signature `s` must be a _Slice_ containing at least 512 data bits; only the first 512 bits are used. The result is `-1` if the signature is valid, `0` otherwise. Notice that [`CHKSIGNU`](#instr-chksignu) is equivalent to [`ROT`](#instr-rot) [`NEWC`](#instr-newc) [`256 STU`](#instr-stu) [`ENDC`](#instr-endc) [`ROTREV`](#instr-rotrev) [`CHKSIGNS`](#instr-chksigns), i.e., to [`CHKSIGNS`](#instr-chksigns) with the first argument `d` set to 256-bit _Slice_ containing `h`. Therefore, if `h` is computed as the hash of some data, these data are hashed _twice_, the second hashing occurring inside [`CHKSIGNS`](#instr-chksigns). | `26` |
-| **`F911`** | `CHKSIGNS` | _`d s k - ?`_ | Checks whether `s` is a valid Ed25519-signature of the data portion of _Slice_ `d` using public key `k`, similarly to [`CHKSIGNU`](#instr-chksignu). If the bit length of _Slice_ `d` is not divisible by eight, throws a cell underflow exception. The verification of Ed25519 signatures is the standard one, with `Sha` used to reduce `d` to the 256-bit number that is actually signed. | `26` |
-### 11.6 Miscellaneous primitives
-| xxxxxxx Opcode | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description | xxxx Gas |
-|:-|:-|:-|:-|:-|
-| **`F940`** | `CDATASIZEQ` | _`c n - x y z -1 or 0`_ | Recursively computes the count of distinct cells `x`, data bits `y`, and cell references `z` in the dag rooted at _Cell_ `c`, effectively returning the total storage used by this dag taking into account the identification of equal cells. The values of `x`, `y`, and `z` are computed by a depth-first traversal of this dag, with a hash table of visited cell hashes used to prevent visits of already-visited cells. The total count of visited cells `x` cannot exceed non-negative _Integer_ `n`; otherwise the computation is aborted before visiting the `(n+1)`-st cell and a zero is returned to indicate failure. If `c` is _Null_, returns `x=y=z=0`. | |
-| **`F941`** | `CDATASIZE` | _`c n - x y z`_ | A non-quiet version of [`CDATASIZEQ`](#instr-cdatasizeq) that throws a cell overflow exception (8) on failure. | |
-| **`F942`** | `SDATASIZEQ` | _`s n - x y z -1 or 0`_ | Similar to [`CDATASIZEQ`](#instr-cdatasizeq), but accepting a _Slice_ `s` instead of a _Cell_. The returned value of `x` does not take into account the cell that contains the slice `s` itself; however, the data bits and the cell references of `s` are accounted for in `y` and `z`. | |
-| **`F943`** | `SDATASIZE` | _`s n - x y z`_ | A non-quiet version of [`SDATASIZEQ`](#instr-sdatasizeq) that throws a cell overflow exception (8) on failure. | |
-### 11.7 Currency manipulation primitives
-| xxxxxxx Opcode | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description | xxxx Gas |
-|:-|:-|:-|:-|:-|
-| **`FA00`** | `LDGRAMS` `LDVARUINT16` | _`s - x s'`_ | Loads (deserializes) a `Gram` or `VarUInteger 16` amount from _Slice_ `s`, and returns the amount as _Integer_ `x` along with the remainder `s'` of `s`. The expected serialization of `x` consists of a 4-bit unsigned big-endian integer `l`, followed by an `8l`-bit unsigned big-endian representation of `x`. The net effect is approximately equivalent to [`4 LDU`](#instr-ldu) [`SWAP`](#instr-swap) [`3 LSHIFT#`](#instr-lshift) [`LDUX`](#instr-ldux). | `26` |
-| **`FA01`** | `LDVARINT16` | _`s - x s'`_ | Similar to [`LDVARUINT16`](#instr-ldgrams), but loads a _signed_ _Integer_ `x`. Approximately equivalent to [`4 LDU`](#instr-ldu) [`SWAP`](#instr-swap) [`3 LSHIFT#`](#instr-lshift) [`LDIX`](#instr-ldix). | `26` |
-| **`FA02`** | `STGRAMS` `STVARUINT16` | _`b x - b'`_ | Stores (serializes) an _Integer_ `x` in the range `0...2^120-1` into _Builder_ `b`, and returns the resulting _Builder_ `b'`. The serialization of `x` consists of a 4-bit unsigned big-endian integer `l`, which is the smallest integer `l>=0`, such that `x<2^(8l)`, followed by an `8l`-bit unsigned big-endian representation of `x`. If `x` does not belong to the supported range, a range check exception is thrown. | `26` |
-| **`FA03`** | `STVARINT16` | _`b x - b'`_ | Similar to [`STVARUINT16`](#instr-stgrams), but serializes a _signed_ _Integer_ `x` in the range `-2^119...2^119-1`. | `26` |
-### 11.8 Message and address manipulation primitives
-| xxxxxxx Opcode | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description | xxxx Gas |
-|:-|:-|:-|:-|:-|
-| **`FA40`** | `LDMSGADDR` | _`s - s' s''`_ | Loads from _Slice_ `s` the only prefix that is a valid `MsgAddress`, and returns both this prefix `s'` and the remainder `s''` of `s` as slices. | `26` |
-| **`FA41`** | `LDMSGADDRQ` | _`s - s' s'' -1 or s 0`_ | A quiet version of [`LDMSGADDR`](#instr-ldmsgaddr): on success, pushes an extra `-1`; on failure, pushes the original `s` and a zero. | `26` |
-| **`FA42`** | `PARSEMSGADDR` | _`s - t`_ | Decomposes _Slice_ `s` containing a valid `MsgAddress` into a _Tuple_ `t` with separate fields of this `MsgAddress`. If `s` is not a valid `MsgAddress`, a cell deserialization exception is thrown. | `26` |
-| **`FA43`** | `PARSEMSGADDRQ` | _`s - t -1 or 0`_ | A quiet version of [`PARSEMSGADDR`](#instr-parsemsgaddr): returns a zero on error instead of throwing an exception. | `26` |
-| **`FA44`** | `REWRITESTDADDR` | _`s - x y`_ | Parses _Slice_ `s` containing a valid `MsgAddressInt` (usually a `msg_addr_std`), applies rewriting from the `anycast` (if present) to the same-length prefix of the address, and returns both the workchain `x` and the 256-bit address `y` as integers. If the address is not 256-bit, or if `s` is not a valid serialization of `MsgAddressInt`, throws a cell deserialization exception. | `26` |
-| **`FA45`** | `REWRITESTDADDRQ` | _`s - x y -1 or 0`_ | A quiet version of primitive [`REWRITESTDADDR`](#instr-rewritestdaddr). | `26` |
-| **`FA46`** | `REWRITEVARADDR` | _`s - x s'`_ | A variant of [`REWRITESTDADDR`](#instr-rewritestdaddr) that returns the (rewritten) address as a _Slice_ `s`, even if it is not exactly 256 bit long (represented by a `msg_addr_var`). | `26` |
-| **`FA47`** | `REWRITEVARADDRQ` | _`s - x s' -1 or 0`_ | A quiet version of primitive [`REWRITEVARADDR`](#instr-rewritevaraddr). | `26` |
-### 11.9 Outbound message and output action primitives
-| xxxxxxx Opcode | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description | xxxx Gas |
-|:-|:-|:-|:-|:-|
-| **`FB00`** | `SENDRAWMSG` | _`c x - `_ | Sends a raw message contained in _Cell `c`_, which should contain a correctly serialized object `Message X`, with the only exception that the source address is allowed to have dummy value `addr_none` (to be automatically replaced with the current smart-contract address), and `ihr_fee`, `fwd_fee`, `created_lt` and `created_at` fields can have arbitrary values (to be rewritten with correct values during the action phase of the current transaction). Integer parameter `x` contains the flags. Currently `x=0` is used for ordinary messages; `x=128` is used for messages that are to carry all the remaining balance of the current smart contract (instead of the value originally indicated in the message); `x=64` is used for messages that carry all the remaining value of the inbound message in addition to the value initially indicated in the new message (if bit 0 is not set, the gas fees are deducted from this amount); `x'=x+1` means that the sender wants to pay transfer fees separately; `x'=x+2` means that any errors arising while processing this message during the action phase should be ignored. Finally, `x'=x+32` means that the current account must be destroyed if its resulting balance is zero. This flag is usually employed together with `+128`. | `526` |
-| **`FB02`** | `RAWRESERVE` | _`x y - `_ | Creates an output action which would reserve exactly `x` nanograms (if `y=0`), at most `x` nanograms (if `y=2`), or all but `x` nanograms (if `y=1` or `y=3`), from the remaining balance of the account. It is roughly equivalent to creating an outbound message carrying `x` nanograms (or `b-x` nanograms, where `b` is the remaining balance) to oneself, so that the subsequent output actions would not be able to spend more money than the remainder. Bit `+2` in `y` means that the external action does not fail if the specified amount cannot be reserved; instead, all remaining balance is reserved. Bit `+8` in `y` means `x:=-x` before performing any further actions. Bit `+4` in `y` means that `x` is increased by the original balance of the current account (before the compute phase), including all extra currencies, before performing any other checks and actions. Currently `x` must be a non-negative integer, and `y` must be in the range `0...15`. | `526` |
-| **`FB03`** | `RAWRESERVEX` | _`x D y - `_ | Similar to [`RAWRESERVE`](#instr-rawreserve), but also accepts a dictionary `D` (represented by a _Cell_ or _Null_) with extra currencies. In this way currencies other than Grams can be reserved. | `526` |
-| **`FB04`** | `SETCODE` | _`c - `_ | Creates an output action that would change this smart contract code to that given by _Cell_ `c`. Notice that this change will take effect only after the successful termination of the current run of the smart contract. | `526` |
-| **`FB06`** | `SETLIBCODE` | _`c x - `_ | Creates an output action that would modify the collection of this smart contract libraries by adding or removing library with code given in _Cell_ `c`. If `x=0`, the library is actually removed if it was previously present in the collection (if not, this action does nothing). If `x=1`, the library is added as a private library, and if `x=2`, the library is added as a public library (and becomes available to all smart contracts if the current smart contract resides in the masterchain); if the library was present in the collection before, its public/private status is changed according to `x`. Values of `x` other than `0...2` are invalid. | `526` |
-| **`FB07`** | `CHANGELIB` | _`h x - `_ | Creates an output action similarly to [`SETLIBCODE`](#instr-setlibcode), but instead of the library code accepts its hash as an unsigned 256-bit integer `h`. If `x!=0` and the library with hash `h` is absent from the library collection of this smart contract, this output action will fail. | `526` |
-
-## 12 Debug primitives
-Opcodes beginning with `FE` are reserved for the debug primitives. These primitives have known fixed operation length and behave as (multibyte) [`NOP`](#instr-nop) operations.
-
-However, when invoked in a TVM instance with debug mode enabled, these primitives can produce a specific output into the text debug log of the TVM instance, never affecting the TVM state.
-
-[`DEBUG`](#instr-debug) and [`DEBUGSTR`](#instr-debugstr) are the two debug primitives, they cover all opcodes that start with `FE`.
-Other primitives listed here have opcodes from the same set. When debug is enabled, they have their specified effects. When debug is disabled, they behave as [`NOP`](#instr-nop).
-
-| xxxxxxx Opcode | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description | xxxx Gas |
-|:-|:-|:-|:-|:-|
-| **`FEnn`** | `{nn} DEBUG` | _`-`_ | `0 <= nn < 240` | `26` |
-| **`FEFnssss`** | `{string} DEBUGSTR` `{string} {x} DEBUGSTRI` | _`-`_ | `0 <= n < 16`. Length of `ssss` is `n+1` bytes. `{string}` is a [string literal](https://github.com/Piterden/TON-docs/blob/master/Fift.%20A%20Brief%20Introduction.md#user-content-29-string-literals). [`DEBUGSTR`](#instr-debugstr): `ssss` is the given string. [`DEBUGSTRI`](#instr-debugstr): `ssss` is one-byte integer `0 <= x <= 255` followed by the given string. | `26` |
-| **`FE00`** | `DUMPSTK` | _`-`_ | Dumps the stack (at most the top 255 values) and shows the total stack depth. | `26` |
-| **`FE2i`** | `s[i] DUMP` | _`-`_ | Dumps `s[i]`. | `26` |
-
-## 13 Codepage primitives
-| xxxxxxx Opcode | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description | xxxx Gas |
-|:-|:-|:-|:-|:-|
-| **`FFnn`** | `[nn] SETCP` | _`-`_ | Selects TVM codepage `0 <= nn < 240`. If the codepage is not supported, throws an invalid opcode exception. | `26` |
-| **`FF00`** | `SETCP0` | _`-`_ | Selects TVM (test) codepage zero as described in this document. | `26` |
-| **`FFFz`** | `[z-16] SETCP` | _`-`_ | Selects TVM codepage `z-16` for `1 <= z <= 15`. Negative codepages `-13...-1` are reserved for restricted versions of TVM needed to validate runs of TVM in other codepages. Negative codepage `-14` is reserved for experimental codepages, not necessarily compatible between different TVM implementations, and should be disabled in the production versions of TVM. | `26` |
-| **`FFF0`** | `SETCPX` | _`c - `_ | Selects codepage `c` with `-2^15 <= c < 2^15` passed in the top of the stack. | `26` |
-
-
diff --git a/docs/learn/tvm-instructions/tvm-exit-codes.md b/docs/learn/tvm-instructions/tvm-exit-codes.md
index 19a57ab935..a54863b6fc 100644
--- a/docs/learn/tvm-instructions/tvm-exit-codes.md
+++ b/docs/learn/tvm-instructions/tvm-exit-codes.md
@@ -14,21 +14,30 @@ The list of standard exit codes contains all universal TVM exit codes defined fo
| `1` | Compute Phase | Alternative successful execution exit code. |
| `2` | Compute Phase | Stack underflow. Last op-code consumed more elements than there are on the stacks. 1 |
| `3` | Compute Phase | Stack overflow. More values have been stored on a stack than allowed by this version of TVM. |
-| `4` | Compute Phase | Integer overflow. Integer does not fit into −2256 ≤ x < 2256 or a division by zero has occurred. |
-| `5` | Compute Phase | Integer out of expected range. |
-| `6` | Compute Phase | Invalid opcode. Instruction is unknown in the current TVM version. |
-| `7` | Compute Phase | Type check error. An argument to a primitive is of an incorrect value type. 1 |
-| `8` | Compute Phase | Cell overflow. Writing to builder is not possible since after operation there would be more than 1023 bits or 4 references. |
-| `9` | Compute Phase | Cell underflow. Read from slice primitive tried to read more bits or references than there are. |
-| `10` | Compute Phase | Dictionary error. Error during manipulation with dictionary (hashmaps). |
-| `11` | Compute Phase | Most oftenly caused by trying to call get-method whose id wasn't found in the code (missing `method_id` modifier or wrong get-method name specified when trying to call it). In [TVM docs](https://ton.org/tvm.pdf) its described as "Unknown error, may be thrown by user programs". |
-| `12` | Compute Phase | Thrown by TVM in situations deemed impossible. |
-| `13` | Compute Phase | Out of gas error. Thrown by TVM when the remaining gas becomes negative. |
-| `-14` | Compute Phase | It means out of gas error, same as `13`. Negative, because it [cannot be faked](https://github.com/ton-blockchain/ton/blob/20758d6bdd0c1327091287e8a620f660d1a9f4da/crypto/vm/vm.cpp#L492) |
-| `32` | Action Phase | Action list is invalid. Set during action phase if c5 register after execution contains unparsable object. |
+| `4` | Compute Phase | Integer overflow. Integer does not fit into −2256 ≤ x < 2256 or a division by zero has occurred. |
+| `5` | Compute Phase | Integer out of expected range. |
+| `6` | Compute Phase | Invalid opcode. Instruction is unknown in the current TVM version. |
+| `7` | Compute Phase | Type check error. An argument to a primitive is of an incorrect value type. 1 |
+| `8` | Compute Phase | Cell overflow. Writing to builder is not possible since after operation there would be more than 1023 bits or 4 references. |
+| `9` | Compute Phase | Cell underflow. Read from slice primitive tried to read more bits or references than there are. |
+| `10` | Compute Phase | Dictionary error. Error during manipulation with dictionary (hashmaps). |
+| `11` | Compute Phase | Most often caused by trying to call get-method whose id wasn't found in the code (missing `method_id` modifier or wrong get-method name specified when trying to call it). In [TVM docs](https://ton.org/tvm.pdf) its described as "Unknown error, may be thrown by user programs". |
+| `12` | Compute Phase | Thrown by TVM in situations deemed impossible. |
+| `13` | Compute Phase | Out of gas error. Thrown by TVM when the remaining gas becomes negative. |
+| `-14` | Compute Phase | It means out of gas error, same as `13`. Negative, because it [cannot be faked](https://github.com/ton-blockchain/ton/blob/20758d6bdd0c1327091287e8a620f660d1a9f4da/crypto/vm/vm.cpp#L492) |
+| `32` | Action Phase | Action list is invalid. Set during action phase if c5 register after execution contains unparsable object. |
| `-32` | Action Phase | (the same as prev 32) - Method ID not found. Returned by TonLib during an attempt to execute non-existent get method. |
-| `34` | Action Phase | Action is invalid or not supported. Set during action phase if current action cannot be applied. |
-| `37` | Action Phase | Not enough TON. Message sends too much TON (or there is not enough TON after deducting fees). |
-| `38` | Action Phase | Not enough extra-currencies. |
+| `33` | Action Phase | Action list is too long. |
+| `34` | Action Phase | Action is invalid or not supported. Set during action phase if current action cannot be applied. |
+| `35` | Action Phase | Invalid Source address in outbound message. |
+| `36` | Action Phase | Invalid Destination address in outbound message. |
+| `37` | Action Phase | Not enough TON. Message sends too much TON (or there is not enough TON after deducting fees). |
+| `38` | Action Phase | Not enough extra-currencies. |
+| `40` | Action Phase | Not enough funds to process a message. This error is thrown when there is only enough gas to cover part of the message, but does not cover it completely. |
+| `43` | Action Phase | The maximum number of cells in the library is exceeded or the maximum depth of the Merkle tree is exceeded. |
-1 If you encounter such exception in a _func_ contract it probably means a type error in `asm` declarations.
+1 If you encounter such exception in a func contract it probably means a type error in asm declarations.
+
+:::info
+Often you can see the exit code `0xffff` (65535 in decimal form). This usually means that the received opcode is unknown to the contract. When writing contracts, this code is set by the developer himself.
+:::
\ No newline at end of file
diff --git a/docs/learn/tvm-instructions/tvm-overview.md b/docs/learn/tvm-instructions/tvm-overview.md
deleted file mode 100644
index 44b5a0d692..0000000000
--- a/docs/learn/tvm-instructions/tvm-overview.md
+++ /dev/null
@@ -1,74 +0,0 @@
-# TVM Overview
-
-All TON Smart Contracts are executed on their own TON Virtual Machine (TVM). TVM is built on the _stack principle_, which makes it efficient and easy to implement.
-
-This document provides a bird's-eye view of how TVM executes transactions.
-
-:::tip
-
-* There is also a detailed specification — [**Whitepaper**](https://ton.org/tvm.pdf)
-* Could be useful — [**TVM C++ implementation**](https://github.com/ton-blockchain/ton/tree/master/crypto/vm)
-
-:::
-
-## Transactions and phases
-When some event happens on the account in one of the TON chains, it causes a **transaction**. The most common event is the "arrival of some message", but generally speaking there could be `tick-tock`, `merge`, `split` and other events.
-
-Each transaction consists of up to 5 phases:
-1. **Storage phase** - in this phase, storage fees accrued by the contract due to the occupation of some space in the chain state are calculated. Read more in [Storage Fees](/develop/smart-contracts/fees#storage-fee).
-2. **Credit phase** - in this phase, the balance of the contract with respect to a (possible) incoming message value and collected storage fee are calculated
-3. **Compute phase** - in this phase, TVM is executed (see below), the result of the TVM execution is an aggregation of `exit_code`, `actions` (serialized list of actions), `gas_details`, `new_storage` and some others.
-4. **Action phase** - if the compute phase was successful, in this phase, `actions` from the compute phase are processed. In particular, actions may include sending messages, updating the smart contract code, updating the libraries etc. Note that some actions may fail during processing (for instance, if we try to send message with more TON than the contract has), in that case the whole transaction may revert or this action may be skipped (it depends on the mode of the actions, in other words, the contract may send a `send-or-revert` or `try-send-if-no-ignore` type of message).
-5. **Bounce phase** - if the compute phase failed (it returned `exit_code >= 2`), in this phase, _bounce message_ is formed for transactions initiated by an incoming message.
-
-## Compute phase
-In this phase, the TVM execution occurs.
-
-### TVM state
-At any given moment, the TVM state is fully determined by 6 properties:
-* Stack (see below)
-* Control registers - (see below) to put it simply, this means up to 16 variables which may be directly set and read during execution
-* Current continuation - object which describes a currently executed sequence of instructions
-* Current codepage - to put it simply, this means the version of TVM which is currently running
-* Gas limits - a set of 4 integer values; the current gas limit gl , the maximal gas limit gm , the remaining gas gr and the gas credit gc
-* Library context - the hashmap of libraries which can be called by TVM
-
-### TVM is a stack machine
-TVM is a last-input-first-output stack machine. In total, there are 7 types of variables which may be stored in stack — three non-cell types:
-* Integer - signed 257-bit integers
-* Tuple - ordered collection of up to 255 elements having arbitrary value types, possibly distinct.
-* Null
-
-And four distinct flavours of cells:
-* Cell - basic (possibly nested) opaque structure used by TON Blockchain for storing all data
-* Slice - special object which allows you to read from a cell
-* Builder - special object which allows you to create new cells
-* Continuation - special object which allows you to use a cell as source of TVM instructions
-
-### Control registers
-* `c0` — Contains the next continuation or return continuation (similar to the subroutine return address in conventional designs). This value must be a Continuation.
-* `c1` — Contains the alternative (return) continuation; this value must be a Continuation.
-* `c2` — Contains the exception handler. This value is a Continuation, invoked whenever an exception is triggered.
-* `c3` — Supporting register, contains the current dictionary, essentially a hashmap containing the code of all functions used in the program. This value must be a Continuation.
-* `c4` — Contains the root of persistent data, or simply the `data` section of the contract. This value is a Cell.
-* `c5` — Contains the output actions. This value is a Cell.
-* `c7` — Contains the root of temporary data. It is a Tuple.
-
-### Initialization of TVM
-
-TVM initializes when transaction execution gets to the Computation phase, and then executes commands (opcodes) from _Current continuation_ until there are no more commands to execute (and no continuation for return jumps).
-
-Detailed description of the initialization process can be found here: [TVM Initialization](/learn/tvm-instructions/tvm-initialization.md)
-
-## TVM instructions
-
-The list of TVM instructions can be found here: [TVM instructions](/learn/tvm-instructions/instructions).
-
-### Result of TVM execution
-Besides exit_code and consumed gas data, TVM indirectly outputs the following data:
-* c4 register - the cell which will be stored as new `data` of the smart-contract (if execution will not be reverted on this or later phases)
-* c5 register - (list of output actions) the cell with last action in the list and reference to the cell with prev action (recursively)
-
-All other register values will be neglected.
-
-Note, that since there is a limitation on max cell-depth `<1024`, and particularly a limitation on c4 and c5 depth `<=512`, there will be a limitation on the number of output actions in one tx `<=255`. If a contract need to send more than that, it may send a message with the request `continue_sending` to itself and send all necessary messages in subsequent transactions.
diff --git a/docs/learn/tvm-instructions/tvm-overview.mdx b/docs/learn/tvm-instructions/tvm-overview.mdx
new file mode 100644
index 0000000000..56e0654e5e
--- /dev/null
+++ b/docs/learn/tvm-instructions/tvm-overview.mdx
@@ -0,0 +1,131 @@
+import Button from '@site/src/components/button'
+
+# TVM Overview
+
+All TON Smart Contracts are executed on their own TON Virtual Machine (TVM). TVM is built on the _stack principle_, which makes it efficient and easy to implement.
+
+This document provides a bird's-eye view of how TVM executes transactions.
+
+:::tip
+* TVM Source — [**TVM C++ implementation**](https://github.com/ton-blockchain/ton/tree/master/crypto/vm)
+:::
+
+
+## TON Course: TVM
+
+:::tip
+Before starting the course, make sure you have a good understanding of the basics of blockchain technology. If you have gaps in your knowledge, we recommend taking the [Blockchain Basics with TON](https://stepik.org/course/201294/promo) ([RU version](https://stepik.org/course/202221/), [CHN version](https://stepik.org/course/200976/)) course.
+:::
+
+The [TON Blockchain Course](https://stepik.org/course/176754/) is a comprehensive guide to TON Blockchain development.
+
+Module 2 completely covers __TVM__, transactions, scalability and business cases.
+
+````mdx-code-block
+
+````
+Check TON Blockchain Course
+````mdx-code-block
+
+````
+````mdx-code-block
+
+````
+CHN
+````mdx-code-block
+
+````
+````mdx-code-block
+
+````
+RU
+````mdx-code-block
+
+````
+
+## Transactions and phases
+When some event happens on the account in one of the TON chains, it causes a **transaction**. The most common event is the "arrival of some message", but generally speaking there could be `tick-tock`, `merge`, `split` and other events.
+
+Each transaction consists of up to 5 phases:
+1. **Storage phase** - in this phase, storage fees accumulated by the contract due to the occupation of some space in the chain state are calculated. Read more in [Storage Fees](/develop/smart-contracts/fees#storage-fee).
+2. **Credit phase** - in this phase, the balance of the contract with respect to a (possible) incoming message value and collected storage fee are calculated.
+3. **Compute phase** - in this phase, TVM is executing the contract (see below) and the result of the contract execution is an aggregation of `exit_code`, `actions` (serialized list of actions), `gas_details`, `new_storage` and some others.
+4. **Action phase** - if the compute phase was successful, in this phase, `actions` from the compute phase are processed. In particular, actions may include sending messages, updating the smart contract code, updating the libraries, etc. Note that some actions may fail during processing (for instance, if we try to send message with more TON than the contract has), in that case the whole transaction may revert or this action may be skipped (it depends on the mode of the actions, in other words, the contract may send a `send-or-revert` or `try-send-if-no-ignore` type of message).
+5. **Bounce phase** - if the compute phase failed (it returned `exit_code >= 2`), in this phase, the _bounce message_ is formed for the transactions initiated by an incoming message.
+
+## Compute phase
+In this phase, the TVM execution occurs.
+
+:::tip
+* TVM 4.3.5 — [**TON Blockchain paper**](https://docs.ton.org/assets/files/tblkch-6aaf006b94ee2843a982ebf21d7c1247.pdf)
+:::
+
+### Compute phase skipped
+
+The computing phase consists in invoking TVM with correct inputs. On some occasions, TVM cannot be invoked at all (e.g., if the account is absent, not initialized, or frozen, and the inbound message being processed has no code or data fields or these fields have an incorrect hash)
+
+This is reflected by corresponding [constructors](https://github.com/ton-blockchain/ton/blob/5c392e0f2d946877bb79a09ed35068f7b0bd333a/crypto/block/block.tlb#L314):
+
+- `cskip_no_state$00` - The [absence of a state](https://testnet.tonviewer.com/transaction/7e78394d082882375a5d21affa6397dec60fc5a3ecbea87f401b0e460fb5c80c) (i.e., smart-contract code and data) in both the account (non-existing, uninitialized, or frozen) and the message.
+
+- `cskip_bad_state$01` - An invalid state passed in the message (i.e., the state's hash differs from the expected value) to a frozen or uninitialized account.
+
+- `cskip_no_gas$10` - The [absence of funds](https://testnet.tonviewer.com/transaction/a1612cde7fd66139a7d04b30f38db192bdb743a8b12054feba3c16061a4cb9a6) to buy gas. (About < 0.00004 TON by [08.2024](https://testnet.tonviewer.com/transaction/9789306d7b29318c90477aa3df6599ee4a897031162ad41a24decb87db65402b))
+
+### TVM state
+At any given moment, the TVM state is fully determined by 6 properties:
+* Stack (see below)
+* Control registers - (see below) to put it simply, this means up to 16 variables which may be directly set and read during execution
+* Current continuation - object which describes a currently executed sequence of instructions
+* Current codepage - in simple terms, this means the version of TVM which is currently running
+* Gas limits - a set of 4 integer values; the current gas limit gl , the maximal gas limit gm , the remaining gas gr and the gas credit gc
+* Library context - the hashmap of libraries which can be called by TVM
+
+### TVM is a stack machine
+TVM is a last-input-first-output stack machine. In total, there are 7 types of variables which may be stored in stack — three non-cell types:
+* Integer - signed 257-bit integers
+* Tuple - ordered collection of up to 255 elements having arbitrary value types, possibly distinct.
+* Null
+
+And four distinct flavours of cells:
+* Cell - basic (possibly nested) opaque structure used by TON Blockchain for storing all data
+* Slice - a special object which allows you to read from a cell
+* Builder - a special object which allows you to create new cells
+* Continuation - a special object which allows you to use a cell as source of TVM instructions
+
+### Control registers
+* `c0` — Contains the next continuation or return continuation (similar to the subroutine return address in conventional designs). This value must be a Continuation.
+* `c1` — Contains the alternative (return) continuation; this value must be a Continuation.
+* `c2` — Contains the exception handler. This value is a Continuation, invoked whenever an exception is triggered.
+* `c3` — Supporting register, contains the current dictionary, essentially a hashmap containing the code of all functions used in the program. This value must be a Continuation.
+* `c4` — Contains the root of persistent data, or simply the `data` section of the contract. This value is a Cell.
+* `c5` — Contains the output actions. This value is a Cell.
+* `c7` — Contains the root of temporary data. It is a Tuple.
+
+### Initialization of TVM
+
+TVM initializes when transaction execution gets to the Computation phase, and then executes commands (opcodes) from _Current continuation_ until there are no more commands to execute (and no continuation for return jumps).
+
+Detailed description of the initialization process can be found here: [TVM Initialization](/learn/tvm-instructions/tvm-initialization.md)
+
+## TVM instructions
+
+The list of TVM instructions can be found here: [TVM instructions](/learn/tvm-instructions/instructions).
+
+### Result of TVM execution
+Besides exit_code and consumed gas data, TVM indirectly outputs the following data:
+* c4 register - the cell which will be stored as new `data` of the smart-contract (if execution will not be reverted on this or later phases)
+* c5 register - (list of output actions) the cell with last action in the list and reference to the cell with prev action (recursively)
+
+All other register values will be neglected.
+
+Note, that since there is a limit on max cell-depth `<1024`, and particularly the limit on c4 and c5 depth `<=512`, there will be a limit on the number of output actions in one tx `<=255`. If a contract needs to send more than that, it may send a message with the request `continue_sending` to itself and send all necessary messages in subsequent transactions.
+
+
+## See Also
+
+- [TVM Instructions](/learn/tvm-instructions/instructions)
+- [TON TVM](https://ton.org/tvm.pdf) TVM Concepts(may include outdated information)
diff --git a/docs/learn/tvm-instructions/tvm-upgrade-2023-07.md b/docs/learn/tvm-instructions/tvm-upgrade-2023-07.md
index 84b6fd4e02..57273f4828 100644
--- a/docs/learn/tvm-instructions/tvm-upgrade-2023-07.md
+++ b/docs/learn/tvm-instructions/tvm-upgrade-2023-07.md
@@ -1,10 +1,9 @@
# TVM Upgrade 2023.07
-:::caution **Work in progress**:
-Some operation codes may be removed, some gas prices are likely to be changed. It is expected that no new opcodes will be added to the list.
+:::tip
+This upgrade launched [run](https://t.me/tonblockchain/223) on the Mainnet from December 2023.
:::
-This upgrade expected to be shipped in testnet by the end of the May and in mainnet by the end of the June.
# c7
@@ -42,33 +41,40 @@ Block ids are presented in the following format:
[ last_mc_blocks:[BlockId0, BlockId1, ..., BlockId15]
prev_key_block:BlockId ] : PrevBlocksInfo
```
-Ids of the last 16 blocks of masterchain are included, as well as the last key block.
+Ids of the last 16 blocks of masterchain are included (or less if masterchain seqno is less than 16), as well as the last key block.
Inclusion of data on shardblocks may cause some data availability issues (due to merge/split events),
it is not necessarily required (since any event/data can by proven using masterchain blocks) and thus we decided not to include it.
# New opcodes
-Rule of thumb when choosing gas cost on new opcodes is that it should not be less than normal (calculated from opcode length) and should spend no more than 20 ns per gas unit.
+Rule of thumb when choosing gas cost on new opcodes is that it should not be less than normal (calculated from opcode length) and should take no more than 20 ns per gas unit.
## Opcodes to work with new c7 values
-26 gas for each
-
-| xxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description |
-|:-|:-|:-|
-| `MYCODE` | _`- c`_ | Retrieve code of smart-contract from c7 |
-| `INCOMINGVALUE` | _`- t`_ | Retrieve value of incoming message from c7 |
-| `STORAGEFEES` | _`- i`_ | Retrieve value of storage phase fees from c7 |
-| `PREVBLOCKSINFOTUPLE` | _`- t`_ | Retrive PrevBlocksInfo: `[last_mc_blocks, prev_key_block]` from c7 |
-| `PREVMCBLOCKS` | _`- t`_ | Retrive only `last_mc_blocks` |
-| `PREVKEYBLOCK` | _`- t`_ | Retrieve only `prev_key_block` |
-| `GLOBALID` | _`- i`_ | Retrieve `global_id` from 19 network config |
+26 gas for each, except for `PREVMCBLOCKS` and `PREVKEYBLOCK` (34 gas).
+
+| xxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description |
+|:-|:-|:--------------------------------------------------------------------|
+| `MYCODE` | _`- c`_ | Retrieves code of smart-contract from c7 |
+| `INCOMINGVALUE` | _`- t`_ | Retrieves value of incoming message from c7 |
+| `STORAGEFEES` | _`- i`_ | Retrieves value of storage phase fees from c7 |
+| `PREVBLOCKSINFOTUPLE` | _`- t`_ | Retrives PrevBlocksInfo: `[last_mc_blocks, prev_key_block]` from c7 |
+| `PREVMCBLOCKS` | _`- t`_ | Retrieves only `last_mc_blocks` |
+| `PREVKEYBLOCK` | _`- t`_ | Retrieves only `prev_key_block` |
+| `GLOBALID` | _`- i`_ | Retrieves `global_id` from 19 network config |
## Gas
-| xxxxxxxxxxxxxx Fift syntax | xxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description |
-|:-|:-|:-|
-| `GASCONSUMED` | _`- g_c`_ | Returns gas consumed by VM so far _26 gas_ |
+| xxxxxxxxxxxxxx Fift syntax | xxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description |
+|:-|:-|:-----------------------------------------------------------------------------|
+| `GASCONSUMED` | _`- g_c`_ | Returns gas consumed by VM so far (including this instruction). _26 gas_ |
## Arithmetics
+New variants of [the division opcode](https://docs.ton.org/learn/tvm-instructions/instructions#52-division) (`A9mscdf`) are added:
+`d=0` takes one additional integer from stack and adds it to the intermediate value before division/rshift. These operations return both the quotient and the remainder (just like `d=3`).
+
+Quiet variants are also available (e.g. `QMULADDDIVMOD` or `QUIET MULADDDIVMOD`).
+
+If return values don't fit into 257-bit integers or the divider is zero, non-quiet operation throws an integer overflow exception. Quiet operations return `NaN` instead of the value that doesn't fit (two `NaN`s if the divider is zero).
+
Gas cost is equal to 10 plus opcode length: 26 for most opcodes, +8 for `LSHIFT#`/`RSHIFT#`, +8 for quiet.
| xxxxxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Stack |
@@ -98,8 +104,6 @@ Gas cost is equal to 10 plus opcode length: 26 for most opcodes, +8 for `LSHIFT#
| `y LSHIFT#ADDDIVMODR` | _`x w z - q=round((x*2^y+w)/z) r=(x*2^y+w)-zq`_ |
| `y LSHIFT#ADDDIVMODC` | _`x w z - q=ceil((x*2^y+w)/z) r=(x*2^y+w)-zq`_ |
-Quiet versions of these instructions are available: `QUIET ADDDIVMOD`, `QUIET 1 MULADDRSHIFTR#MOD` etc.
-
## Stack operations
Currently arguments of all stack operations are bounded by 256.
That means that if stack become deeper than 256 it becomes difficult to manage deep stack elements.
@@ -114,15 +118,18 @@ Currently only two hash operations are available in TVM: calculation of represen
`HASHEXT[A][R]_(HASH)` family of operations is added:
-| xxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description |
-|:-|:-|:-|
-| `HASHEXT_(HASH)` | _`s_1 ... s_n n - h`_ | Calculate and return hash of the concatenation of slices (or builders) `s_1...s_n`. |
-| `HASHEXTR_(HASH)` | _`s_n ... s_1 n - h`_ | Same thing, but arguments are given in reverse order. |
-| `HASHEXTA_(HASH)` | _`b s_1 ... s_n n - b'`_ | Append the resulting hash to a builder `b` instead of pushing it to the stack. |
-| `HASHEXTAR_(HASH)` | _`b s_n ... s_1 n - b'`_ | Arguments in reverse order, append hash to builder. |
+| xxxxxxxxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description |
+|:-|:-|:--------------------------------------------------------------------------------------|
+| `HASHEXT_(HASH)` | _`s_1 ... s_n n - h`_ | Calculates and returns hash of the concatenation of slices (or builders) `s_1...s_n`. |
+| `HASHEXTR_(HASH)` | _`s_n ... s_1 n - h`_ | Same thing, but arguments are given in reverse order. |
+| `HASHEXTA_(HASH)` | _`b s_1 ... s_n n - b'`_ | Appends the resulting hash to a builder `b` instead of pushing it to the stack. |
+| `HASHEXTAR_(HASH)` | _`b s_n ... s_1 n - b'`_ | Arguments are given in reverse order, appends hash to builder. |
Only the bits from root cells of `s_i` are used.
-Note that each chunk `s_i` may contain non-integer number of bytes. However, the sum of bits of all chunks should be divisible by 8.
+
+Each chunk `s_i` may contain non-integer number of bytes. However, the sum of bits of all chunks should be divisible by 8.
+Note that TON uses most-significant bit ordering, so when two slices with non-integer number of bytes are concatenated, bits from the first slice become most-significant bits.
+
Gas consumption depends on the number of hashed bytes and the chosen algorithm. Additional 1 gas unit is consumed per chunk.
If `[A]` is not enabled, the result of hashing will be returned as an unsigned integer if fits 256 bits or tuple of ints otherwise.
@@ -131,19 +138,21 @@ The following algorithms are available:
- `SHA256` - openssl implementation, 1/33 gas per byte, hash is 256 bits.
- `SHA512` - openssl implementation, 1/16 gas per byte, hash is 512 bits.
- `BLAKE2B` - openssl implementation, 1/19 gas per byte, hash is 512 bits.
-- `KECCAK256` - [ethereum compatible implementation](http://keccak.noekeon.org/) , 1/11 gas per byte, hash is 256 bits.
-- `KECCAK512` - [ethereum compatible implementation](http://keccak.noekeon.org/) , 1/6 gas per byte, hash is 512 bits.
+- `KECCAK256` - [ethereum compatible implementation](http://keccak.noekeon.org/), 1/11 gas per byte, hash is 256 bits.
+- `KECCAK512` - [ethereum compatible implementation](http://keccak.noekeon.org/), 1/6 gas per byte, hash is 512 bits.
+
+Gas usage is rounded down.
## Crypto
Currently the only cryptographic algorithm available is `CHKSIGN`: check the Ed25519-signature of a hash `h` for a public key `k`.
-For compatibility with prev generation blockchains such as Bitcoin and Ethereum we need `secp256k1` signature checking algo.
-For modern cryptographic algorithms the bare minimum is curve addition and multiplication.
-For compatibility with Ethereum 2.0 PoS and some other modern cryptography we need BLS-signature scheme on bls12-381 curve.
-For some secure hardware secp256r1 == P256 == prime256v1 is needed.
+- For compatibility with prev generation blockchains such as Bitcoin and Ethereum we also need checking `secp256k1` signatures.
+- For modern cryptographic algorithms the bare minimum is curve addition and multiplication.
+- For compatibility with Ethereum 2.0 PoS and some other modern cryptography we need BLS-signature scheme on bls12-381 curve.
+- For some secure hardware secp256r1 == P256 == prime256v1 is needed.
### secp256k1
-Bitcoin/ethereum signatures. Uses libsecp256k1 implementation (https://github.com/bitcoin-core/secp256k1).
+Bitcoin/ethereum signatures. Uses [libsecp256k1 implementation](https://github.com/bitcoin-core/secp256k1).
| xxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description |
|:-|:-|:-|
@@ -161,7 +170,7 @@ Uses OpenSSL implementation. Interface is similar to `CHKSIGNS`/`CHKSIGNU`. Comp
### Ristretto
Extended docs are [here](https://ristretto.group/). In short, Curve25519 was developed with performance in mind, however it exhibits symmetry due to which group elements have multiple representations. Simpler protocols such as Schnorr signatures or Diffie-Hellman apply tricks at the protocol level to mitigate some issues, but break key derivation and key blinding schemes. And those tricks do not scale to more complex protocols such as Bulletproofs. Ristretto is an arithmetic abstraction over Curve25519 such that each group element corresponds to a unique point, which is the requirement for most cryptographic protocols. Ristretto is essentially a compression/decompression protocol for Curve25519 that offers the required arithmetic abstraction. As a result, crypto protocols are easy to write correctly, while benefiting from the high performance of Curve25519.
-Ristretto operation allow calculating curve operations on Curve25519 (the reverse is not true), thus we can consider that we add both Ristretto and Curve25519 curve operation in one step.
+Ristretto operations allow calculating curve operations on Curve25519 (the reverse is not true), thus we can consider that we add both Ristretto and Curve25519 curve operation in one step.
[libsodium](https://github.com/jedisct1/libsodium/) implementation is used.
@@ -169,20 +178,20 @@ All ristretto-255 points are represented in TVM as 256-bit unsigned integers.
Non-quiet operations throw `range_chk` if arguments are not valid encoded points.
Zero point is represented as integer `0`.
-| xxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description |
-|:-|:-|:-|
-| `RIST255_FROMHASH` | _`h1 h2 - x`_ | Deterministically generate a valid point `x` from a 512-bit hash (given as two 256-bit integers) _626 gas_ |
-| `RIST255_VALIDATE` | _`x -`_ | Check that integer `x` is a valid representation of some curve point. Throw `range_chk` on error. _226 gas_ |
-| `RIST255_ADD` | _`x y - x+y`_ | Addition of two points on a curve _626 gas_ |
-| `RIST255_SUB` | _`x y - x-y`_ | Subtraction of two points on curve _626 gas_ |
-| `RIST255_MUL` | _`x n - x*n`_ | Multiply point `x` by a scalar `n`. _2026 gas_ |
-| `RIST255_MULBASE` | _`n - g*n`_ | Multiply the generator point `g` by a scalar `n`. _776 gas_ |
-| `RIST255_PUSHL` | _`- l`_ | Push integer `l=2^252+27742317777372353535851937790883648493`, which is the order of the group. _26 gas_ |
-| `RIST255_QVALIDATE` | _`x - 0 or -1`_ | Quiet version of `RIST255_VALIDATE`. _234 gas_ |
-| `RIST255_QADD` | _`x y - 0 or x+y -1`_ | Quiet version of `RIST255_ADD`. _634 gas_ |
-| `RIST255_QSUB` | _`x y - 0 or x-y -1`_ | Quiet version of `RIST255_SUB`. _634 gas_ |
-| `RIST255_QMUL` | _`x n - 0 or x*n -1`_ | Quiet version of `RIST255_MUL`. _2034 gas_ |
-| `RIST255_QMULBASE` | _`n - 0 or g*n -1`_ | Quiet version of `RIST255_MULBASE`. _784 gas_ |
+| xxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description |
+|:-|:-|:------------------------------------------------------------------------------------------------------------------|
+| `RIST255_FROMHASH` | _`h1 h2 - x`_ | Deterministically generates a valid point `x` from a 512-bit hash (given as two 256-bit integers). _626 gas_ |
+| `RIST255_VALIDATE` | _`x -`_ | Checks that integer `x` is a valid representation of some curve point. Throws `range_chk` on error. _226 gas_ |
+| `RIST255_ADD` | _`x y - x+y`_ | Addition of two points on a curve. _626 gas_ |
+| `RIST255_SUB` | _`x y - x-y`_ | Subtraction of two points on curve. _626 gas_ |
+| `RIST255_MUL` | _`x n - x*n`_ | Multiplies point `x` by a scalar `n`. Any `n` is valid, including negative. _2026 gas_ |
+| `RIST255_MULBASE` | _`n - g*n`_ | Multiplies the generator point `g` by a scalar `n`. Any `n` is valid, including negative. _776 gas_ |
+| `RIST255_PUSHL` | _`- l`_ | Pushes integer `l=2^252+27742317777372353535851937790883648493`, which is the order of the group. _26 gas_ |
+| `RIST255_QVALIDATE` | _`x - 0 or -1`_ | Quiet version of `RIST255_VALIDATE`. _234 gas_ |
+| `RIST255_QADD` | _`x y - 0 or x+y -1`_ | Quiet version of `RIST255_ADD`. _634 gas_ |
+| `RIST255_QSUB` | _`x y - 0 or x-y -1`_ | Quiet version of `RIST255_SUB`. _634 gas_ |
+| `RIST255_QMUL` | _`x n - 0 or x*n -1`_ | Quiet version of `RIST255_MUL`. _2034 gas_ |
+| `RIST255_QMULBASE` | _`n - 0 or g*n -1`_ | Quiet version of `RIST255_MULBASE`. _784 gas_ |
### BLS12-381
Operations on a pairing friendly BLS12-381 curve. [BLST](https://github.com/supranational/blst) implementation is used. Also, ops for BLS signature scheme which is based on this curve.
@@ -194,41 +203,58 @@ BLS values are represented in TVM in the following way:
- Elements of field FP2: 96-byte slice.
- Messages: slice. Number of bits should be divisible by 8.
-| xxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description |
-|:-|:-|:-|
-| `BLS_VERIFY` | _`pk msg sgn - bool`_ | Check BLS signature, return true on success. _61000 gas_ |
-| `BLS_AGGREGATE` | _`sig_1 ... sig_n n - sig`_ | Aggregate signatures. `n>0`. _`gas=n*4350-2650`_ |
-| `BLS_FASTAGGREGATEVERIFY`- | _`pk_1 ... pk_n msg sig - bool`_ | Check aggregated BLS signature for keys `pk_1...pk_n` and message `msg`. `n>0`. _`gas=58000+n*3000`_ |
-| `BLS_AGGREGATEVERIFY` | _`pk_1 msg_1 ... pk_n msg_n n sgn - bool`_ | Check aggregated BLS signature for kay-message pairs `pk_1 msg_1...pk_n msg_n`. `n>0`. _`gas=38500+n*22500`_ |
-| `BLS_G1_ADD` | _`x y - x+y`_ | Addition on G1. _3900 gas_ |
-| `BLS_G1_SUB` | _`x y - x-y`_ | Subtraction on G1. _3900 gas_ |
-| `BLS_G1_NEG` | _`x - -x`_ | Negation on G1. _750 gas_ |
-| `BLS_G1_MUL` | _`x s - x*s`_ | Multiply G1 point `x` by scalar `s`. _5200 gas_ |
-| `BLS_G1_MULTIEXP` | _`x_1 s_1 ... x_n s_n - x_1*s_1+...+x_n*s_n`_ | Calculate `x_1*s_1+...+x_n*s_n` for G1 points `x_i` and scalars `n_i`. _`gas=11409+n*630+n/floor(max(log2(n),4))*8820`_ |
-| `BLS_G1_ZERO` | _`- zero`_ | Push zero point in G1. _34 gas_ |
-| `BLS_MAP_TO_G1` | _`f - x`_ | Convert FP element `f` to a G1 point. _2350 gas_ |
-| `BLS_G1_INGROUP` | _`x - bool`_ | Check that slice `x` represents a valid element of G1. _2950 gas_ |
-| `BLS_G1_ISZERO` | _`x - bool`_ | Check that G1 point `x` is equal to zero. _34 gas_ |
-| `BLS_G2_ADD` | _`x y - x+y`_ | Addition on G2. _6134 gas_ |
-| `BLS_G2_SUB` | _`x y - x-y`_ | Subtraction on G2. _6134 gas_ |
-| `BLS_G2_NEG` | _`x - -x`_ | Negation on G2. _1584 gas_ |
-| `BLS_G2_MUL` | _`x s - x*s`_ | Multiply G2 point `x` by scalar `s`. _10550 gas_ |
-| `BLS_G2_MULTIEXP` | _`x_1 s_1 ... x_n s_n - x_1*s_1+...+x_n*s_n`_ | Calculate `x_1*s_1+...+x_n*s_n` for G2 points `x_i` and scalars `n_i`. _`gas=30422+n*1280+n/floor(max(log2(n),4))*22840`_ |
-| `BLS_G2_ZERO` | _`- zero`_ | Push zero point in G2. _34 gas_ |
-| `BLS_MAP_TO_G2` | _`f - x`_ | Convert FP2 element `f` to a G2 point. _7950 gas_ |
-| `BLS_G2_INGROUP` | _`x - bool`_ | Check that slice `x` represents a valid element of G2. _4250 gas_ |
-| `BLS_G2_ISZERO` | _`x - bool`_ | Check that G2 point `x` is equal to zero. _34 gas_ |
-| `BLS_PAIRING` | _`x_1 y_1 ... x_n y_n n - bool`_ | Given G1 points `x_i` and G2 points `y_i`, calculate and multiply pairings of `x_i,y_i`. Return true if the result is the multiplicative identity in FP12. _`gas=20034+n*11800`_ |
-| `BLS_PUSHR` | _`- r`_ | Push the order of G1 and G2 (approx. `2^255`). _`gas=34`_ |
+When input value is a point or a field element, the slice may have more than 48/96 bytes. In this case only the first 48/96 bytes are taken. If the slice has less bytes (or if message size is not divisible by 8), cell underflow exception is thrown.
+
+#### High-level operations
+These are high-level operations for verifying BLS signatures.
+
+| xxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description |
+|:-|:-|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `BLS_VERIFY` | _`pk msg sgn - bool`_ | Checks BLS signature, return true on success, false otherwise. _61034 gas_ |
+| `BLS_AGGREGATE` | _`sig_1 ... sig_n n - sig`_ | Aggregates signatures. `n>0`. Throw exception if `n=0` or if some `sig_i` is not a valid signature. _`gas=n*4350-2616`_ |
+| `BLS_FASTAGGREGATEVERIFY`- | _`pk_1 ... pk_n n msg sig - bool`_ | Checks aggregated BLS signature for keys `pk_1...pk_n` and message `msg`. Return true on success, false otherwise. Return false if `n=0`. _`gas=58034+n*3000`_ |
+| `BLS_AGGREGATEVERIFY` | _`pk_1 msg_1 ... pk_n msg_n n sgn - bool`_ | Checks aggregated BLS signature for key-message pairs `pk_1 msg_1...pk_n msg_n`. Return true on success, false otherwise. Return false if `n=0`. _`gas=38534+n*22500`_ |
+
+`VERIFY` instructions don't throw exception on invalid signatures and public keys (except for cell underflow exceptions), they return false instead.
+
+#### Low-level operations
+These are arithmetic operations on group elements.
+
+| xxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description |
+|:-|:-|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `BLS_G1_ADD` | _`x y - x+y`_ | Addition on G1. _3934 gas_ |
+| `BLS_G1_SUB` | _`x y - x-y`_ | Subtraction on G1. _3934 gas_ |
+| `BLS_G1_NEG` | _`x - -x`_ | Negation on G1. _784 gas_ |
+| `BLS_G1_MUL` | _`x s - x*s`_ | Multiplies G1 point `x` by scalar `s`. Any `s` is valid, including negative. _5234 gas_ |
+| `BLS_G1_MULTIEXP` | _`x_1 s_1 ... x_n s_n n - x_1*s_1+...+x_n*s_n`_ | Calculates `x_1*s_1+...+x_n*s_n` for G1 points `x_i` and scalars `s_i`. Returns zero point if `n=0`. Any `s_i` is valid, including negative. _`gas=11409+n*630+n/floor(max(log2(n),4))*8820`_ |
+| `BLS_G1_ZERO` | _`- zero`_ | Pushes zero point in G1. _34 gas_ |
+| `BLS_MAP_TO_G1` | _`f - x`_ | Converts FP element `f` to a G1 point. _2384 gas_ |
+| `BLS_G1_INGROUP` | _`x - bool`_ | Checks that slice `x` represents a valid element of G1. _2984 gas_ |
+| `BLS_G1_ISZERO` | _`x - bool`_ | Checks that G1 point `x` is equal to zero. _34 gas_ |
+| `BLS_G2_ADD` | _`x y - x+y`_ | Addition on G2. _6134 gas_ |
+| `BLS_G2_SUB` | _`x y - x-y`_ | Subtraction on G2. _6134 gas_ |
+| `BLS_G2_NEG` | _`x - -x`_ | Negation on G2. _1584 gas_ |
+| `BLS_G2_MUL` | _`x s - x*s`_ | Multiplies G2 point `x` by scalar `s`. Any `s` is valid, including negative. _10584 gas_ |
+| `BLS_G2_MULTIEXP` | _`x_1 s_1 ... x_n s_n n - x_1*s_1+...+x_n*s_n`_ | Calculates `x_1*s_1+...+x_n*s_n` for G2 points `x_i` and scalars `s_i`. Returns zero point if `n=0`. Any `s_i` is valid, including negative. _`gas=30422+n*1280+n/floor(max(log2(n),4))*22840`_ |
+| `BLS_G2_ZERO` | _`- zero`_ | Pushes zero point in G2. _34 gas_ |
+| `BLS_MAP_TO_G2` | _`f - x`_ | Converts FP2 element `f` to a G2 point. _7984 gas_ |
+| `BLS_G2_INGROUP` | _`x - bool`_ | Checks that slice `x` represents a valid element of G2. _4284 gas_ |
+| `BLS_G2_ISZERO` | _`x - bool`_ | Checks that G2 point `x` is equal to zero. _34 gas_ |
+| `BLS_PAIRING` | _`x_1 y_1 ... x_n y_n n - bool`_ | Given G1 points `x_i` and G2 points `y_i`, calculates and multiply pairings of `x_i,y_i`. Returns true if the result is the multiplicative identity in FP12, false otherwise. Returns false if `n=0`. _`gas=20034+n*11800`_ |
+| `BLS_PUSHR` | _`- r`_ | Pushes the order of G1 and G2 (approx. `2^255`). _34 gas_ |
+
+`INGROUP`, `ISZERO` don't throw exception on invalid points (except for cell underflow exceptions), they return false instead.
+
+Other arithmetic operations throw exception on invalid curve points. Note that they don't check whether given curve points belong to group G1/G2. Use `INGROUP` instruction to check this.
## RUNVM
Currently there is no way for code in TVM to call external untrusted code "in sandbox". In other words, external code always can irreversibly update code, data of contract, or set actions (such as sending all money).
`RUNVM` instruction allows to spawn an independent VM instance, run desired code and get needed data (stack, registers, gas consumption etc) without risks of polluting caller's state. Running arbitrary code in a safe way may be useful for [v4-style plugins](/participate/wallets/contracts#wallet-v4), Tact's `init` style subcontract calculation etc.
-| xxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description |
-|:-|:-|:-|
-| `flags RUNVM` | _`x_1 ... x_n n code [r] [c4] [c7] [g_l] [g_m] - x'_1 ... x'_m exitcode [data'] [c4'] [c5] [g_c]`_ | Run child VM with code `code` and stack `x_1...x_n`. Return the resulting stack `x'_1...x'_m` and exitcode. Other arguments and return values are enabled by flags, see below. |
-| `RUNVMX` | _`x_1 ... x_n n code [r] [c4] [c7] [g_l] [g_m] flags - x'_1 ... x'_m exitcode [data'] [c4'] [c5] [g_c]`_ | Same thing. but pop flags from stack. |
+| xxxxxxxxxxxxx Fift syntax | xxxxxxxxxxxxxxxxx Stack | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Description |
+|:-|:-|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `flags RUNVM` | _`x_1 ... x_n n code [r] [c4] [c7] [g_l] [g_m] - x'_1 ... x'_m exitcode [data'] [c4'] [c5] [g_c]`_ | Runs child VM with code `code` and stack `x_1...x_n`. Returns the resulting stack `x'_1...x'_m` and exitcode. Other arguments and return values are enabled by flags, see below. |
+| `RUNVMX` | _`x_1 ... x_n n code [r] [c4] [c7] [g_l] [g_m] flags - x'_1 ... x'_m exitcode [data'] [c4'] [c5] [g_c]`_ | Same thing, but pops flags from stack. |
Flags are similar to `runvmx` in fift:
- `+1`: set c3 to code
@@ -250,4 +276,4 @@ Gas cost:
Currently it is difficult to calculate cost of sending message in contract (which leads to some approximations like in [jettons](https://github.com/ton-blockchain/token-contract/blob/main/ft/jetton-wallet.fc#L94)) and impossible to bounce request back if action phase is incorrect. It is also impossible to accurately subtract from incoming message sum of "constant fee for contract logic" and "gas expenses".
- `SENDMSG` takes a cell and mode as input. Creates an output action and returns a fee for creating a message. Mode has the same effect as in the case of SENDRAWMSG. Additionally `+1024` means - do not create an action, only estimate fee. Other modes affect the fee calculation as follows: `+64` substitutes the entire balance of the incoming message as an outcoming value (slightly inaccurate, gas expenses that cannot be estimated before the computation is completed are not taken into account), `+128` substitutes the value of the entire balance of the contract before the start of the computation phase (slightly inaccurate, since gas expenses that cannot be estimated before the completion of the computation phase are not taken into account).
-- `SENDRAWMSG`,`RAWRESERVE`,`SETLIBRARY` - `+16` flag is added, that means in the case of action fail - bounce transaction. Won't work if `+2` is used
+- `SENDRAWMSG`, `RAWRESERVE`, `SETLIBCODE`, `CHANGELIB` - `+16` flag is added, that means in the case of action fail - bounce transaction. No effect if `+2` is used.
diff --git a/docs/participate/README.md b/docs/participate/README.md
index 8ec4352b32..9ceaf53fa2 100644
--- a/docs/participate/README.md
+++ b/docs/participate/README.md
@@ -12,7 +12,7 @@ It is also meant to offer essential frameworks (explorers, wallets, TEPs) that a
### Join TON Community
* [TON Enhancement Proposals (TEPs)](https://github.com/ton-blockchain/TEPs)
-* [Ask a Question about TON on answers.ton.org](https://answers.ton.org/)
+* [Discover TON innovations at TON Research](https://tonresear.ch/)
* [Stake with TON Nominators](/participate/network-maintenance/nominators)
### Bridges
@@ -25,6 +25,7 @@ It is also meant to offer essential frameworks (explorers, wallets, TEPs) that a
* [Discover Node Types in TON](/participate/nodes/node-types)
* [Run your Full Node or Validator](/participate/run-nodes/full-node)
* [TON Validator maintenance & security](/participate/nodes/node-maintenance-and-security)
+* [Run MyTonCtrl in Docker](/participate/run-nodes/run-docker)
## Participate in TON Web3
@@ -35,4 +36,4 @@ It is also meant to offer essential frameworks (explorers, wallets, TEPs) that a
### TON Proxy
-* [How to open any TON Site?](/participate/web3/how-to-open-any-ton-site)
\ No newline at end of file
+* [How to open any TON Site?](/participate/web3/how-to-open-any-ton-site)
diff --git a/docs/participate/explorers.mdx b/docs/participate/explorers.mdx
index 09443af61e..42c328ca58 100644
--- a/docs/participate/explorers.mdx
+++ b/docs/participate/explorers.mdx
@@ -20,6 +20,14 @@ Among TON explorers, you can distinguish several categories:
This division into categories is largely conditional and one explorer can belong to several categories at the same time. So let's not pay too much attention to this.
+
+## Address Alias in Explorers
+
+Make your service address more user-friendly by using an address alias. Create Pull Requests (PRs) according to the provided guidelines:
+
+- [tonkeeper/ton-assets](https://github.com/tonkeeper/ton-assets) - Tonviewer.com alias
+- [catchain/address-book](https://github.com/catchain/address-book)- Tonscan.org alias
+
## General functionality
Let's start with the general functionality that is present in all explorers.
@@ -28,9 +36,9 @@ Almost all explorers have the ability to find out information about balances, tr
Next, we will consider several explorers that can be attributed to each of these categories.
-## TON Scan
+## TON Scan.org
-Good explorer for everyday use. It has a convenient interface, a lot of information and a search function. Any search is performed by the public [address book](https://github.com/catchain/tonscan/blob/master/src/addrbook.json) (TON Foundation, OKX and etc.)
+Good explorer for everyday use. It provides a comprehensive view of the TON Blockchain, allowing users to search for transactions, addresses, blocks, and more. Any search is performed against the public [address book](https://github.com/catchain/tonscan/blob/master/src/addrbook.json) (TON Foundation, OKX and etc.)
### Features
@@ -45,6 +53,17 @@ Good explorer for everyday use. It has a convenient interface, a lot of informat
- URL: https://tonscan.org/
- Testnet URL: https://testnet.tonscan.org/
+## TON Scan.com
+
+### Features
+
+- Transaction aggregation analytics
+- Transaction Traces
+
+### Links
+
+- URL: https://tonscan.com/
+
## Ton Whales Explorer
This explorer is more oriented towards developers than ordinary users.
@@ -113,6 +132,34 @@ Also, it has a feature that allows you to see the computation phase of the trans
- URL: https://dton.io/
+## TON NFTscan
+
+This explorer is specifically designed for Non-Fungible Tokens (NFTs) on the TON Blockchain. It allows users to explore, track, and verify NFT transactions, contracts, and metadata.
+
+### Features
+
+- Convenient for regular users
+- Useful information for traders, such as daily volume
+- NFT collection ranking
+
+### Links
+
+- URL: https://ton.nftscan.com/
+
+## TonStat
+
+Displays various statistics such as number of registered network addresses and wallets, volume of Toncoin burned, volume of Toncoin staked, volume of NFTs issued, number of validators and a number of other metrics.
+
+### Features
+
+- Convenient for regular users
+- Useful information for traders, such as daily volume
+- DeFi information
+
+### Links
+
+- URL: https://www.tonstat.com/
+
## Want to be in this list?
Please, write to one of the [maintainers](/docs/contribute/maintainers.md).
diff --git a/docs/participate/network-maintenance/custom-overlays.md b/docs/participate/network-maintenance/custom-overlays.md
new file mode 100644
index 0000000000..ddb6d28717
--- /dev/null
+++ b/docs/participate/network-maintenance/custom-overlays.md
@@ -0,0 +1,94 @@
+# Custom overlays
+
+TON `v2024.04` update introduces the ability to use custom overlays.
+Currently they can be used only for broadcasting external messages. The main idea is to create private overlay with
+sender nodes and validators. Only sender nodes can create broadcasts with external messages which will be (hopefully)
+received by block collator and get into the block.
+
+## Default custom overlays
+
+Mytonctrl uses default custom overlays available at https://ton-blockchain.github.io/fallback_custom_overlays.json. To
+stop participation in default custom overlays run commands
+```bash
+MyTonCtrl> set useDefaultCustomOverlays false
+MyTonCtrl> delete_custom_overlay default
+```
+
+## Create custom overlay
+
+### Collect adnl addresses
+
+To add validators to a custom overlay you can use either their `fullnode adnl id` available with `validator-console -c getconfig`
+or `validator adnl id` which can be found in mytonctrl's status.
+To add liteservers to a custom overlay you must use their `fullnode adnl id`.
+
+### Create a config file
+
+Create a config file in format:
+
+```json
+{
+ "adnl_address_hex_1": {
+ "msg_sender": true,
+ "msg_sender_priority": 1
+ },
+ "adnl_address_hex_2": {
+ "msg_sender": false
+ },
+ ...
+}
+```
+
+`msg_sender_priority` determines the order of external message inclusion to blocks: first processed messages from higher priority source. Messages from public overlay and local LS have priority 0.
+
+**Note, all nodes listed in config should participate in overlay (in other words they need to add overlay with exactly this config), otherwise connectivity will be poor and broadcasts will fail**
+
+There is special word `@validators` to create a dynamic custom overlay that mytonctrl will generate automatically
+each round adding all current validators.
+
+### Add custom overlay
+
+Use mytonctrl command to add custom overlay:
+
+```bash
+MyTonCtrl> add_custom_overlay
+```
+
+Note, that name and config file **must** be the same on all overlay members. Check that overlay has been created using
+mytonctrl `list_custom_overlays` command.
+
+### Debug
+
+You can set node verbosity level equals to 4 and grep logs with "CustomOverlay" word.
+
+## Delete custom overlay
+
+To remove custom overlay from a node, use mytonctrl command `delete_custom_overlay `.
+If the overlay is dynamic (i.e. there is `@validators` word in config) it will be deleted within one minute, otherwise it will be removed instantly.
+To make sure that node has deleted custom overlay check `list_custom_overlays` mytonctrl and `showcustomoverlays` validator-console commands.
+
+## Low level
+
+List of validator-console commands to work with custom overlays:
+
+* `addcustomoverlay ` - add custom overlay to local node. Note, that this config must be in a format other than config for mytonctrl:
+ ```json
+ {
+ "name": "OverlayName",
+ "nodes": [
+ {
+ "adnl_id": "adnl_address_b64_1",
+ "msg_sender": true,
+ "msg_sender_priority": 1
+ },
+ {
+ "adnl_id": "adnl_address_b64_2",
+ "msg_sender": false
+ }, ...
+ ]
+ }
+ ```
+* `delcustomoverlay ` - delete custom overlay from node.
+* `showcustomoverlays` - show list of custom overlays node knows about.
+
+
diff --git a/docs/participate/network-maintenance/nominator-pool.mdx b/docs/participate/network-maintenance/nominator-pool.mdx
new file mode 100644
index 0000000000..fe2b4d5724
--- /dev/null
+++ b/docs/participate/network-maintenance/nominator-pool.mdx
@@ -0,0 +1,118 @@
+# Nominator Pool
+
+## Running the Validator in Nominator Pool Mode
+
+1. Set up the hardware for the validator - you will need 8 vCPUs, 128GB memory, 1TB SSD, a fixed IP address, and 1Gb/s internet speed.
+
+ For maintaining network stability, it's recommended to distribute validator nodes in different geographical locations worldwide rather than concentrating them in a single data center. You can use [this site](https://status.toncenter.com/) to assess the load of various locations. The map indicates high data center utilization in Europe, especially in Finland, Germany, and Paris. Therefore, using providers such as Hetzner and OVH is not recommended.
+
+ > Ensure your hardware matches or exceeds the specifications above. Running the validator on insufficient hardware negatively impacts the network and could result in penalties.
+
+ > Note that as of May 2021, Hetzner has prohibited mining on its servers, and this ban includes both PoW and PoS algorithms. Even installing a regular node may be considered a violation of their terms of service.
+
+ > **Recommended providers include:** [Amazon](https://aws.amazon.com/), [DigitalOcean](https://www.digitalocean.com/), [Linode](https://www.linode.com/), [Alibaba Cloud](https://alibabacloud.com/), [Latitude](https://www.latitude.sh/).
+
+2. Install and synchronize **mytonctrl** as described in the guide [here](/participate/run-nodes/full-node#how-to-run-a-node-video).
+
+ You can also refer to this [Video Instruction](https://ton.org/docs/#/nodes/run-node) for additional help.
+
+3. Transfer 1 TON to the validator wallet address shown in the `wl` list.
+
+4. Use the `aw` command to activate your validator wallet.
+
+5. Activate pool mode:
+
+ ```bash
+ enable_mode nominator-pool
+ set stake null
+ ```
+
+6. Create two pools (for even and odd validation rounds):
+
+ ```bash
+ new_pool p1 0 1 1000 300000
+ new_pool p2 0 1 1001 300000
+ ```
+
+ where:
+ * `p1` is the pool name;
+ * `0` % is the validator's reward share (e.g., use 40 for 40%);
+ * `1` is the maximum number of nominators in the pool (should be <= 40);
+ * `1000` TON is the minimum validator stake (should be >= 1K TON);
+ * `300000` TON is the minimum nominator stake (should be >= 10K TON);
+
+ > (!) Pool configurations do not have to be identical, you can add 1 to the minimum stake of one pool to make them different.
+
+ > (!) Use https://tonmon.xyz/ to determine the current minimum validator stake.
+
+7. Type `pools_list` to display pool addresses:
+
+ ```bash
+ pools_list
+ Name Status Balance Address
+ p1 empty 0 0f98YhXA9wnr0d5XRXT-I2yH54nyQzn0tuAYC4FunT780qIT
+ p2 empty 0 0f9qtmnzs2-PumMisKDmv6KNjNfOMDQG70mQdp-BcAhnV5jL
+ ```
+
+8. Send 1 TON to each pool and activate the pools:
+
+ ```bash
+ mg validator_wallet_001 0f98YhXA9wnr0d5XRXT-I2yH54nyQzn0tuAYC4FunT780qIT 1
+ mg validator_wallet_001 0f9qtmnzs2-PumMisKDmv6KNjNfOMDQG70mQdp-BcAhnV5jL 1
+ activate_pool p1
+ activate_pool p2
+ ```
+
+9. Type `pools_list` to display pools:
+
+ ```bash
+ pools_list
+ Name Status Balance Address
+ p1 active 0.731199733 kf98YhXA9wnr0d5XRXT-I2yH54nyQzn0tuAYC4FunT780v_W
+ p2 active 0.731199806 kf9qtmnzs2-PumMisKDmv6KNjNfOMDQG70mQdp-BcAhnV8UO
+ ```
+
+10. Open each pool via the link "https://tonscan.org/nominator/" and verify pool configurations.
+
+11. Proceed with the validator deposit to each pool:
+
+ ```bash
+ deposit_to_pool validator_wallet_001 1005
+ deposit_to_pool validator_wallet_001 1005
+ ```
+
+ In these commands, `1005` TON is the deposit amount. Be aware that 1 TON will be deducted by the pool for processing the deposit.
+
+12. Proceed with the nominator deposit to each pool:
+
+ Visit the pool link (from **Step 9**) and click **ADD STAKE**.
+ You can also make a deposit using **mytonctrl**, using the following commands:
+
+ ```bash
+ mg nominator_wallet_001 300001 -C d
+ mg nominator_wallet_001 300001 -C d
+ ```
+
+ > (!) The nominator wallet must be initialized in basechain (workchain 0).
+
+ > (!) Keep in mind that the validator wallet and nominator wallet must be stored separately! The validator wallet should be stored on the server with the validator node to ensure processing of all system transactions. Meanwhile, the nominator wallet should be stored in your cold cryptocurrency wallet.
+
+ > To withdraw a nominator deposit, send a transaction with the comment `w` to the pool address (attach 1 TON to process the transaction). You can also perform this action using **mytonctrl**.
+
+13. Invite nominators to deposit into your pools. The participation in validation will commence automatically.
+
+ > (!) Ensure that you have at least 200 TON/month in your validator wallet for operation fees.
+
+## Pool Configuration
+
+If you're intending to lend to yourself, use `new_pool p1 0 1 1000 300000` (maximum of 1 nominator, 0% validator share).
+
+If you're creating a pool for numerous nominators, you might use something like this: `new_pool p1 40 40 10000 10000` (maximum of 40 nominators, 40% validator share, minimum participant stakes of 10K TON).
+
+## Transitioning a Regular Validator to Nominator Pool Mode
+
+1. Input `set stake 0` to discontinue election participation.
+
+2. Await the return of both your stakes from the elector.
+
+3. Proceed with the steps under "Running the Validator in Nominator Pool Mode" from the **4th step** onwards.
diff --git a/docs/participate/network-maintenance/nominators.md b/docs/participate/network-maintenance/nominators.md
index 9c53c091fb..e2840bdf49 100644
--- a/docs/participate/network-maintenance/nominators.md
+++ b/docs/participate/network-maintenance/nominators.md
@@ -1,4 +1,4 @@
-# Nominator Pools
+# Staking with Nominator Pools
## Overview
@@ -23,6 +23,10 @@ To become a validator, you must meet two requirements: have a high-performance s
### Nominators
+:::info
+New version of Nominator Pool available, read more in the Single Nominator and Vesting Contract pages.
+:::
+
It's evident that not everyone can afford to have 100,000s of Toncoin on their balance – here's where nominators come into play. Simply put, the nominator is a user who lends his TON to validators. Every time the validator earns a reward by validating blocks, it is distributed between the involved participants.
Some time ago, Ton Whales ran the first staking pool on TON with a minimum deposit of 50 TON. Later, TON Foundation launched the first open nominator pool. Now, users may stake Toncoin in a fully-decentralized way, starting with **10,000 TON**.
diff --git a/docs/participate/network-maintenance/persistent-states.md b/docs/participate/network-maintenance/persistent-states.md
index 84b218ce2f..057eeb6547 100644
--- a/docs/participate/network-maintenance/persistent-states.md
+++ b/docs/participate/network-maintenance/persistent-states.md
@@ -7,19 +7,16 @@ TTL of a state from period `x` is equal to `2^(18 + ctz(x))`, where `ctz(x)` is
That means that persistent states are created every 1.5 days, half of them have TTL of `2^18` seconds (3 days), half of the remaining states have TTL of `2^19` seconds (6 days) and so on.
-In 2022 there is the following long-term (at least 3 months) persistent states (times in the future are approximate):
+In 2024 there is the following long-term (at least 3 months) persistent states:
| Block seqno | Block time | TTL | Expires at |
|--:|--:|--:|--:|
-| 18155329 | 2022-02-07 01:31:53 | 777 days | 2024-03-24 18:52:57 |
-| 19365422 | 2022-03-27 14:36:58 | 97 days | 2022-07-02 16:47:06 |
-| | 2022-05-14 20:00:00 | 194 days | 2022-11-24 23:00:00 |
-| | 2022-07-02 09:00:00 | 97 days | 2022-10-07 10:00:00 |
-| | 2022-08-19 22:00:00 | 388 days | 2023-09-12 06:00:00 |
-| | 2022-10-07 11:00:00 | 97 days | 2023-01-12 12:00:00 |
-| | 2022-11-25 00:00:00 | 194 days | 2023-06-07 03:00:00 |
-| | 2022-11-25 00:00:00 | 194 days | 2023-06-07 03:00:00 |
-| 27747086 | 2022-03-02 05:08:11 | 1553 days | 2027-06-02 18:50:19 |
+| [8930706](https://explorer.toncoin.org/search?workchain=-1&shard=8000000000000000&seqno=8930706) | 2021-01-14 15:08:40 | 12427 days | 2055-01-24 08:45:44 |
+| [27747086](https://explorer.toncoin.org/search?workchain=-1&shard=8000000000000000&seqno=27747086) | 2023-03-02 05:08:11 | 1553 days | 2027-06-02 19:50:19 |
+| [32638387](https://explorer.toncoin.org/search?workchain=-1&shard=8000000000000000&seqno=32638387) | 2023-09-12 09:27:36 | 388 days | 2024-10-04 18:08:08 |
+| [34835953](https://explorer.toncoin.org/search?workchain=-1&shard=8000000000000000&seqno=34835953) | 2023-12-18 11:37:48 | 194 days | 2024-06-29 15:58:04 |
+| [35893070](https://explorer.toncoin.org/search?workchain=-1&shard=8000000000000000&seqno=35893070) | 2024-02-05 00:42:50 | 97 days | 2024-05-12 02:52:58 |
+| [36907647](https://explorer.toncoin.org/search?workchain=-1&shard=8000000000000000&seqno=36907647) | 2024-03-24 13:47:57 | 776 days | 2026-05-10 07:09:01 |
When the node starts for the first time, it has to download a persistent state. This is implemented in [validator/manager-init.cpp](https://github.com/ton-blockchain/ton/blob/master/validator/manager-init.cpp).
diff --git a/docs/participate/network-maintenance/single-nominator.mdx b/docs/participate/network-maintenance/single-nominator.mdx
new file mode 100644
index 0000000000..3ab5765e77
--- /dev/null
+++ b/docs/participate/network-maintenance/single-nominator.mdx
@@ -0,0 +1,416 @@
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+# Single Nominator Pool
+
+[Single Nominator](https://github.com/orbs-network/single-nominator) is a TON smart contract that enables secure validation for TON blockchain. The contract is designed for TON validators that have enough self stake to validate by themselves without relying on third-party nominators stakes. The contract provides an alternative simplified implementation for the Nominator Pool smart contract that supports a Single Nominator only.
+
+### Set up single-nominator
+
+:::caution
+Before start make sure you have topped up and [activated](/participate/run-nodes/become-validator#activate-the-wallets) validator's wallet.
+:::
+
+1. Enable single nominator mode
+
+```bash
+MyTonCtrl> enable_mode single-nominator
+```
+
+2. Check if single-nominator mode is enabled.
+
+```bash
+MyTonCtrl> status_modes
+Name Status Description
+single-nominator enabled Orbs's single nominator pools.
+```
+
+3. Create pool
+
+```bash
+MyTonCtrl> new_single_pool
+```
+
+If you have already created pool it's possible to import it:
+
+```bash
+MyTonCtrl> import_pool
+```
+
+4. Type `pools_list` to display pool addresses
+
+```bash
+MyTonCtrl> pools_list
+Name Status Balance Version Address
+test-pool empty 0.0 spool_r2 kf_JcC5pn3etTAdwOnc16_tyMmKE8-ftNUnf0OnUjAIdDJpX
+```
+
+5. Activate the pool
+
+```bash
+MyTonCtrl> activate_single_pool
+```
+
+After successfully activated pool:
+
+```bash
+MyTonCtrl> pools_list
+Name Status Balance Version Address
+test-pool active 0.99389 spool_r2 kf_JcC5pn3etTAdwOnc16_tyMmKE8-ftNUnf0OnUjAIdDJpX
+```
+
+Now you can work with this pool via mytonctrl like with a standard nominator pool.
+
+:::info
+If the pool's balance is enough to participate in both rounds (`balance > min_stake_amount * 2`) then MyTonCtrl will automatically participate in both rounds using `stake = balance / 2`, unless user sets stake manually using command `set stake`. This behaviour is different from using a nominator pool but similar to staking using validator wallet.
+:::
+
+## Start without mytonctrl
+
+#### Prepare launched Validator
+
+ If you have mytonctrl installed and validator running:
+
+ 1. Stop validation and withdraw all funds.
+
+#### Prepare from the beginning
+ If you had no Validator before, do the following:
+ 1. [Run a Validator](/participate/run-nodes/full-node) and make sure it's synced.
+ 2. Stop validation and withdraw all funds.
+
+
+### Prepare Single Nominator
+
+
+1. Install [nodejs](https://nodejs.org/en) v.16 and later and npm ([detailed instructions](https://github.com/nodesource/distributions#debian-and-ubuntu-based-distributions))
+
+2. Install `ts-node` and `arg` module
+
+```bash
+$ sudo apt install ts-node
+$ sudo npm i arg -g
+```
+
+4. Create symlinks for compilers:
+
+```bash
+$ sudo ln -s /usr/bin/ton/crypto/fift /usr/local/bin/fift
+$ sudo ln -s /usr/bin/ton/crypto/func /usr/local/bin/func
+```
+
+5. Run test to make sure everything is set up properly:
+
+```bash
+$ npm run test
+```
+
+6. Replace mytonctrl nominator-pool scripts: https://raw.githubusercontent.com/orbs-network/single-nominator/main/mytonctrl-scripts/install-pool-scripts.sh
+
+### Create Single Nominator Pool
+
+1. Get Toncenter API key from a Telegram [@tonapibot](https://t.me/tonapibot)
+2. Set env variables:
+
+```bash
+export OWNER_ADDRESS=
+export VALIDATOR_ADDRESS=
+export TON_ENDPOINT=https://toncenter.com/api/v2/jsonRPC
+export TON_API_KEY=
+```
+
+2. Create deployer address:
+
+```bash
+$ npm run init-deploy-wallet
+Insufficient Deployer [EQAo5U...yGgbvR] funds 0
+```
+
+3. Topup deployer address with 2.1 TON
+4. Deploy pool contract, you will get pool address: `Ef-kC0..._WLqgs`:
+
+```
+$ npm run deploy
+```
+
+5. Convert address to .addr:
+
+```
+$ fift -s ./scripts/fift/str-to-addr.fif Ef-kC0..._WLqgs
+```
+
+(Saving address to file single-nominator.addr)
+
+6. Backup deployer private key "./build/deploy.config.json" and "single-nominator.addr" files
+7. Copy "single-nominator.addr" to "mytoncore/pools/single-nominator-1.addr"
+8. Send stake from owner address to single nominator address
+
+### Withdrawals from Single Nominator
+
+Using wallets to withdraw from Single Nominator
+Fift:
+
+1. Create "withdraw.boc" request with amount:
+
+```bash
+$ fift -s ./scripts/fift/withdraw.fif
+```
+
+2. Create and sign request from owner's wallet:
+
+```bash
+$ fift -s wallet-v3.fif -B withdraw.boc
+```
+
+3. Broadcast query:
+
+```bash
+$ lite-client -C global.config.json -c 'sendfile wallet-query.boc'
+tons
+```
+
+1. Create "withdraw.boc" request with amount:
+
+```bash
+$ fift -s ./scripts/fift/withdraw.fif
+```
+
+2. Send request to single nominator address:
+
+a.
+
+```bash
+$ tons wallet transfer --body withdraw.boc
+tonkeeper
+```
+
+b.
+
+```
+npm link typescript
+```
+
+c.
+
+```
+npx ts-node scripts/ts/withdraw-deeplink.ts
+```
+
+d. Open deeplink on the owner's phone
+
+## Deposit pool
+
+You can make a deposit using **MyTonCtrl**, using the following commands:
+
+```sh
+MyTonCtrl> mg
+```
+
+or
+
+```sh
+MyTonCtrl> deposit_to_pool
+```
+
+which deposits pool from validator wallet.
+
+Or use the following steps:
+
+1. Go to the pool’s page https://tonscan.org/nominator/.
+
+2. Make sure that the information about the pool is fully displayed, if the pool has the wrong smart contract, there will be no information.
+
+3. Press the `ADD STAKE` button or scan the QR-code using Tonkeeper or any other TON Wallet.
+
+4. After you are transferred to the wallet, please, enter the amount of TON and then send the transaction. After that TON coins will be added to staking.
+
+If the wallet does not open automatically, you can send the transaction manually by copying the pool address. Send it through any TON wallet. From the sent transaction, 1 TON will be debited as a commission for processing the deposit.
+
+
+## Withdraw funds
+
+You can also withdraw funds using the following command:
+
+```sh
+MyTonCtrl> withdraw_from_pool
+```
+
+Or you can create and send transaction manually:
+
+
+
+
+```js
+import { Address, beginCell, internal, storeMessageRelaxed, toNano } from "@ton/core";
+
+async function main() {
+ const single_nominator_address = Address.parse('single nominator address');
+ const WITHDRAW_OP = 0x1000
+ const amount = 50000
+
+ const messageBody = beginCell()
+ .storeUint(WITHDRAW_OP, 32) // op code for withdrawal
+ .storeUint(0, 64) // query_id
+ .storeCoins(amount) // amount to withdraw
+ .endCell();
+
+ const internalMessage = internal({
+ to: single_nominator_address,
+ value: toNano('1'),
+ bounce: true,
+ body: messageBody
+ });
+}
+```
+
+
+
+
+
+```go
+func WithdrawSingleNominatorMessage(single_nominator_address string, query_id, amount uint64) (*tonconnect.Message, error) {
+
+ const WITHDRAW_OP = 0x1000
+
+ payload, _ := cell.BeginCell().
+ MustStoreUInt(WITHDRAW_OP, 32). // op code for withdrawal
+ MustStoreUInt(query_id, 64). // query_id
+ MustStoreCoins(amount). // amount to withdraw
+ EndCell().MarshalJSON()
+
+ msg, err := tonconnect.NewMessage(
+ single_nominator_address,
+ tlb.MustFromTON("1").Nano().String(), // nanocoins to transfer/compute message
+ tonconnect.WithPayload(payload))
+
+ if err != nil {
+ return nil, err
+ }
+
+ return msg, nil
+}
+```
+
+
+
+
+
+
+## Election process
+
+### Set up a Single Nominator Pool
+
+Configure the Single Nominator Pool contract using the [following]((/participate/network-maintenance/single-nominator#set-up-single-nominator)) instructions.
+
+### Join the elections
+
+[Deposit](/participate/network-maintenance/single-nominator#deposit-pool) minimum stake amount to the Single Nominator Pool.
+
+**MyTonCtrl** will automatically join the elections. You can set the stake amount that mytonctrl sends to the [Elector contract](/develop/smart-contracts/governance#elector) ~ every 18 hours on Mainnet and 2 hours on Testnet.
+
+```sh
+MyTonCtrl> set stake 90000
+```
+
+**Minimum stake** amount could be found using `status` command.
+
+![](/img/docs/single-nominator/tetsnet-conf.png)
+
+You can set `stake` as `null` and it will be calculated according to the `stakePercent` value (could be checked with `status_settings` command).
+
+It's possible to check is election has already been started:
+
+```bash
+MyTonCtrl> status
+```
+
+and for Testnet:
+
+```bash
+MyTonCtrl> status fast
+```
+
+As example:
+
+![](/img/docs/single-nominator/election-status.png)
+
+
+If the election has been started and Single Nominator Pool is activated, validator should **automatically** send **ElectorNewStake** message to the Elector contract at the beginning of the next round.
+
+Check validator wallet:
+
+```sh
+MyTonCtrl> wl
+Name Status Balance Ver Wch Address
+validator_wallet_001 active 995.828585374 v1 -1 kf_dctjwS4tqWdeG4GcCLJ53rkgxZOGGrdDzHJ_mxPkm_Xct
+```
+
+Then check it transaction history:
+
+```sh
+MyTonCtrl> vas kf_dctjwS4tqWdeG4GcCLJ53rkgxZOGGrdDzHJ_mxPkm_Xct
+Address Status Balance Version
+kf_dctjwS4tqWdeG4GcCLJ53rkgxZOGGrdDzHJ_mxPkm_Xct active 995.828585374 v1r3
+
+Code hash
+c3b9bb03936742cfbb9dcdd3a5e1f3204837f613ef141f273952aa41235d289e
+
+Time Coins From/To
+39 minutes ago >>> 1.3 kf_hz3BIXrn5npis1cPX5gE9msp1nMTYKZ3l4obzc8phrBfF
+```
+
+This **ElectorNewStake** transaction in Single Nominator contract history in Tonviewer:
+
+![](/img/docs/single-nominator/new-stake.png)
+
+On the above example **MyTonCtrl** automatically stake `90000` Toncoins on the Elector contract.
+
+### Checking Validator Status
+
+At the beginning of the next round check **MyTonCtrl** validator status with `status` command (`status fast` on Testnet).
+
+![](/img/docs/single-nominator/status-validator.png)
+
+You can confirm if your node has become a full validator by checking the following conditions:
+
+1. **Validator Efficiency** - An efficiency of the local validator should be green and not `n/a`.
+2. **Validator Index** - The validator index should be greater than -1.
+
+
+### Checking profit
+
+At the end of the round **MyTonCtrl** sends **ElectorRecoverStakeRequest** message to the Elector contract. It responses with `stake + profit` amount of Toncoins to your Single Nominator Pool.
+
+![](/img/docs/single-nominator/validator-profit.png)
+
+You can also check transactions history of your pool with `vas` command:
+
+![](/img/docs/single-nominator/validator-profit-vas.png)
+
+### Stop participating
+
+If user doesn't want to take part in validating anymore:
+
+1. Disable validator mode:
+
+```bash
+MyTonCtrl> disable_mode validator
+```
+
+2. [Withdraw](/participate/network-maintenance/single-nominator#withdraw-funds) all funds from the Single Nominator contract to the owner wallet.
+
+## Transitioning a Regular Validator to Nominator Pool Mode
+
+1. Disable `validator` mode to discontinue election participation.
+2. Await the return of both your stakes from the elector.
+3. Proceed with the following [steps](/participate/network-maintenance/single-nominator#set-up-single-nominator).
+
+
+## See Also
+
+* [Single Nominator Pool contract](https://github.com/orbs-network/single-nominator)
+* [Vesting Contract](/participate/network-maintenance/vesting-contract)
+* [single-nominator-quick-how-to-09-25](https://telegra.ph/single-nominator-quick-how-to-09-25)
+
+
+
+
diff --git a/docs/participate/network-maintenance/staking-incentives.md b/docs/participate/network-maintenance/staking-incentives.md
index 8ef1a584ad..43870f437e 100644
--- a/docs/participate/network-maintenance/staking-incentives.md
+++ b/docs/participate/network-maintenance/staking-incentives.md
@@ -1,7 +1,8 @@
-# TON Validators and staking-incentives
+# Staking Incentives
## Election and Staking
+
TON Blockchain makes use of the Proof of Stake (PoS) consensus algorithm which means, like all PoS networks, that the network’s security and stability is maintained by a set of network validators. In particular, validators propose candidates for new blocks (made up of transaction batches), while other validators _validate_ and approve them via digital signatures.
@@ -15,7 +16,47 @@ For each shardchain and masterchain a dedicated set of validators exists. Sets o
In contrast, each shardchain is validated by a set of 23 validators (defined as Network Parameter `Config28:shard_validators_num`) and rotated randomly every 1000 seconds (Network Parameter `Config28:shard_validators_lifetime`).
-## Positive incentives
+## Values of Stakes: Max Effective Stake
+
+The current `max_factor` in config is __3__, meaning the stake of the _smallest_ validator cannot be more than three times less than the stake of the _largest_ one.
+
+The formula with the config parameters:
+
+`max_factor` = [`max_stake_factor`](https://tonviewer.com/config#17) / [`validators_elected_for`](https://tonviewer.com/config#15)
+
+### (Simplified) Selection Algorithm
+
+This algorithm, run by the [Elector smart contract](/develop/smart-contracts/governance#elector), selects the best validator candidates based on the stake they have committed. Here's a breakdown of how it works:
+
+1. **Initial Selection**: Elector considers all candidates who have staked more than a set minimum amount (300K, as specified in the [configuration](https://tonviewer.com/config#17)).
+
+2. **Ordering Candidates**: These candidates are then arranged from highest to lowest based on their stake.
+
+3. **Narrowing Down**:
+ - If the number of candidates exceeds the maximum allowed number of validators ([see configuration](https://tonviewer.com/config#16)), those with the lowest stakes are excluded.
+ - The Elector then evaluates each potential group of candidates, starting from the largest group and moving to smaller ones:
+ - It examines the top candidates in the ordered list, increasing the number one by one.
+ - For each candidate, Elector calculates their 'effective stake'. If a candidate's stake is significantly higher than the minimum, it's adjusted down (e.g., if someone staked 310k and the minimum is 100k, but there's a rule capping at three times the minimum, their effective stake is considered as 300k).
+ - It sums up the effective stakes of all candidates in this group.
+
+4. **Final Selection**: The group of candidates with the highest total effective stake is chosen as the validators by the Elector.
+
+
+#### Validator Selection Algorithm
+
+Based on the available stakes of potential validators, optimal values for the minimum and maximum stake are determined, with the aim of maximizing the magnitude of the total stake:
+
+1. Elector takes all applicants who have a stake higher than the minimum ([300K in config](https://tonviewer.com/config#17)).
+2. Elector sorts them in _descending_ order of stake.
+3. If there are more participants than the [maximum number](https://tonviewer.com/config#16) of validators, Elector discards the tail of the list. Then Elector does the following:
+
+ * For each cycle __i__ from _1 to N_ (the remaining number of participants), it takes the first __i__ applications from the sorted list.
+ * It calculates the effective stake, considering the `max_factor`. That is, if a person has put in 310k, but with a `max_factor` of 3, and the minimum stake in the list is 100k Toncoins, then the effective stake will be min(310k, 3*100k) = 300k. One validator node may use up to 600k TON (in this example) in two rounds (half in odd rounds, half in even rounds). To increase the stake, it is necessary to set up multiple validator nodes.
+ * It calculates the total effective stake of all __i__ participants.
+
+Once Elector finds such an __i__, where the total effective stake is maximal, we declare these __i__ participants as validators.
+
+## Positive Incentives
Similarly to all blockchain networks, each transaction on TON requires a computation fee called [gas](https://blog.ton.org/what-is-blockchain) used to conduct network storage and the transaction processing on-chain. On TON, these fees are accumulated within the Elector contract in a reward pool.
@@ -38,23 +79,72 @@ Learn current TON Blockchain stats [here](https://tontech.io/stats/).
:::
-## Negative incentives
+## Negative Incentives
On TON Blockchain, there are generally two ways validators can be penalized for misbehaving: idle and malicious misbehaving; both of which are prohibited and may result in being fined (in a process called slashing) for their actions.
If a validator does not participate in block creation and transaction signing for a significant amount of time during a validation round, it is potentially fined using the _Standard fine_ parameter. As of April 2023, the Standard fine accrued is 101 TON (Network Parameter `ConfigParam40:MisbehaviourPunishmentConfig`).
+On TON, slashing penalties (fines given to validators) allow any network participant to file a complaint if they believe a validator is misbehaving. During this process, the participant issuing the complaint must attach cryptographic proofs of misbehavior for Elector submission. During the `stake_held_for` dispute resolution period, all validators operating on the network check the validity of complaints and vote whether they will pursue the complaint collectively (while determining the legitimacy of misbehaving proofs and fine allotment).
+
+Upon reaching 66% validator approval (measured by an equal voting weight), a slashing penalty is deducted from the validator and withdrawn from the validator’s total stake. The validation process for penalization and complaint resolution is typically conducted automatically using the MyTonCtrl.
+
+
+## Decentralized System of Penalties
+
:::info
-TON is planning to increase the _Standard fine_ for validators by the end of 2023.
+The following system of penalising poorly performing validators fully operational September 9, 2024.
:::
-On TON, slashing penalties (fines given to validators) allow any network participant to file a complaint if they believe a validator is misbehaving. During this process, the participant issuing the complaint must attach cryptographic proofs of misbehavior for Elector submission. During the `stake_held_for` dispute resolution period, all validators operating on the network check the validity of complaints and vote whether they will pursue the complaint collectively (while determining the legitimacy of misbehaving proofs and fine allotment).
+### Determination of Poor Work
-Upon reaching 66% validator approval (measured by an equal voting weight), a slashing penalty is deducted from the validator and withdrawn from the validator’s total stake. The validation process for penalization and complaint resolution is typically conducted automatically using the MyTonCtrl.
+The TON is supplied with the [lite-client](https://github.com/newton-blockchain/ton/tree/master/lite-client) utility. In lite-client there is a `checkloadall` command.
+This command analyses how many blocks the validator should have processed, and how many it actually processed in a given period of time.
+
+If the validator processed less than 90% of the expected number of blocks during a validation round, it is considered to be performing poorly and should be penalised.
+:::info
+Learn more about technical description of the process [here](https://github.com/ton-blockchain/TIPs/issues/13#issuecomment-786627474)
+:::
+### Complain Workflow
+
+- Anyone can make complain and get reward on right complain.
+- Validation of complain maintain by Validators and fully decentralized.
+
+#### Make Complain
+
+After each validation round (~18 hours), the validator stakes of validators that participated in that round are on the Elector smart contract for another ~9 hours.
+During this time, anyone can send a complaint against a validator who performed poorly in said round. This happens on-chain on the Elector smart contract.
+
+#### Validation of Complaint
+
+After each validation round, validators receive a list of complaints from the Elector smart contract and double-check them by calling `checkloadall`.
+In case the complaint is validated, they on-chain vote in favour of that complaint.
+
+These actions are built into `mytonctrl` and happen automatically.
+If the complaint has 66% of the validators' votes (by their weight), a penalty is taken off from the validator's stake.
+There is no way for anyone to single-handedly fine anyone.
+
+[@tonstatus_notifications](https://t.me/tonstatus_notifications) - list of penalised validators each round.
+
+
+### Fine Value
+
+The amount of the fine is fixed and equals 101 TON(Network Parameter `ConfigParam40:MisbehaviourPunishmentConfig`), which is roughly equal to the validator's income per round.
+
+Value of fine may change, due the audience and the number of transactions in TON is growing rapidly and it is vital that the quality of work is at its best.
+
+### Fine Distribution
+
+The fine is distributed among the validators minus network costs and a small reward (~8 TON) to the first complainer who sent the correct complaint to the Elector.
+
+### Validator Guidelines
+To prevent your Validator node from being fined, it is advisable to ensure that the hardware, monitoring, and validator operations are set up properly.
+Please make sure you're complying with the [validator maintain guidelines](/participate/run-nodes/become-validator#maintain-guidelines).
+If you don't want to do this please consider using staking services https://ton.org/stake.
## See Also
-* [Running a Full Node (Validator)](/participate/run-nodes/full-node)
+* [Running a Validator](/participate/run-nodes/become-validator)
* [Transaction Fees](/develop/smart-contracts/fees)
* [What is blockchain? What is a smart contract? What is gas?](https://blog.ton.org/what-is-blockchain)
\ No newline at end of file
diff --git a/docs/participate/network-maintenance/vesting-contract.mdx b/docs/participate/network-maintenance/vesting-contract.mdx
new file mode 100644
index 0000000000..1d64123a72
--- /dev/null
+++ b/docs/participate/network-maintenance/vesting-contract.mdx
@@ -0,0 +1,157 @@
+# Vesting Contract
+
+This contract allows you to lock a certain amount of Toncoin for a specified time and gradually unlock them.
+
+## Vesting Parameters
+
+Vesting parameters are unchanged and is set during deployment.
+
+`vesting_total_amount` - in nanotons, the total amount of locked Toncoins.
+
+`vesting_start_time` - unixtime, the starting point of the vesting period, until this moment the `vesting_total_amount` is locked, after that it starts to unlock according to other parameters.
+
+`vesting_total_duration` - total vesting duration in seconds (e.g. `31104000` for one year).
+
+`unlock_period` - unlock period in seconds (e.g. `2592000` for once a month).
+
+`cliff_duration` - starting cliff period in seconds (e.g. `5184000` for 2 months).
+
+`vesting_sender_address` - the address to which you can return the Toncoins (even if they are locked) at any time; also this address can append the whitelist.
+
+`owner_address` - the one to whom the vesting was issued, from this address, he can initiate the sending of Toncoins from the vesting contract.
+
+You can get this parameters by `get_vesting_data()` get-method.
+
+The parameters must satisfy the following conditions:
+
+```
+vesting_total_duration > 0
+vesting_total_duration <= 135 years (2^32 seconds)
+unlock_period > 0
+unlock_period <= vesting_total_duration
+cliff_duration >= 0
+cliff_duration < vesting_total_duration
+vesting_total_duration mod unlock_period == 0
+cliff_duration mod unlock_period == 0
+```
+
+Although the smart contract does not check for compliance with these conditions, after the contract is deployed and before sending Toncoins to it, the user can verify that all parameters are OK by get-method.
+
+## Lock
+
+Before the `vesting_start_time`, all `vesting_total_amount` are locked.
+
+Starting from `vesting_start_time` the amount starts to unlock proportionately.
+
+For example if `vesting_total_duration` is 10 months, and `unlock_period` is 1 month, and `vesting_total_amount` is 500 TON then every month will unlock 500*(10/100)=50 TON, and in 10 months all 500 TON will be unlocked.
+
+If there is a cliff period, nothing is unlocked during this cliff period, and after it has passed, the amount is unlocked according to the formula above.
+
+For example if `cliff_period` is 3 months, and the other parameters are the same as in the previous example, then first 3 months nothing will be unlocked and on 3 months 150 TON will be unlocked at once (and then 50 TON every month).
+
+Get-method `get_locked_amount(int at_time)` allows you to calculate how much will be locked at a certain point in time.
+
+You can only send the locked Toncoins to the whitelist addresses or `vesting_sender_address`.
+
+You can send the unlocked Toncoins whenever and wherever you like.
+
+## Whitelist
+
+Whitelist is a list of addresses to which you can send Toncoins, even if coins are still locked.
+
+Get-method `get_whitelist()` returns all whitelist addresses as list of (wc, hash_part) tuples.
+
+Get-method `is_whitelisted(slice address)` checks to see if this address is on the whitelist.
+
+`vesting_sender_address` can append new addresses to whitelist at any time by `op::add_whitelist` message.
+
+Unable to remove an address from the whitelist.
+
+Also, locked coins can always be sent to the `vesting_sender_address` (it doesn't need to be added to the whitelist separately).
+
+## Top-up
+
+You can send Toncoins to vesting contract from any address.
+
+## Wallet smart contract
+
+This contract is designed similar to the [standard wallet V3 smart contract](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/wallet3-code.fc).
+
+In his data, he keeps `seqno`, `subwallet_id`, `public_key` and accepts external messages of the same format.
+
+Get-methods `seqno()`, `get_subwallet_id()` and `get_public_key()` are available.
+
+Unlike a standard wallet, vesting contract allows you to send only one message at a time.
+
+## Send
+
+The owner of the public key can initiate the sending of Toncoins from the vesting contract by an external message, just like in standard wallets.
+
+The Toncoin sending can also be initiated by an `op::send` internal message sent from the `owner_address`.
+
+In practice, both the public key and the `owner_address` are owned by the same user.
+
+## Whitelist restrictions
+
+Messages that can be sent to the `vesting_sender_address` have the following restrictions:
+
+- only `send_mode == 3` allowed;
+
+
+In most cases, addresses are added to the whitelist to allow the user to validate using locked coins or to stake locked coins into the pools.
+
+To avoid theft of Toncoins, messages that can be sent to the whitelist have the following restrictions:
+
+- only `send_mode == 3` allowed;
+
+- only bounceable messages allowed;
+
+- no `state_init` attachment allowed;
+
+If destination is system elector address:
+
+- only `op::elector_new_stake`, `op::elector_recover_stake`, `op::vote_for_complaint`, `op::vote_for_proposal` operations allowed;
+
+If destination is system config address:
+
+- only `op::vote_for_proposal` operation allowed;
+
+For other destinations:
+
+- allowed empty messages and empty text messages;
+- allowed text messages starts only with "d", "w", "D", "W";
+- allowed `op::single_nominator_pool_withdraw`, `op::single_nominator_pool_change_validator`, `op::ton_stakers_deposit`, `op::jetton_burn`, `op::ton_stakers_vote`, `op::vote_for_proposal`, `op::vote_for_complaint` operations;
+
+There are no restrictions on addresses not included in the whitelist.
+
+No restrictions apply when sending unlocked Toncoins, even if we send to whitelist or `vesting_sender_address`.
+
+## Project structure
+
+- `contracts` - source code of all the smart contracts of the project and their dependencies.
+- `wrappers` - wrapper classes (implementing `Contract` from ton-core) for the contracts, including any [de]serialization primitives and compilation functions.
+- `tests` - tests for the contracts.
+- `scripts` - scripts used by the project, mainly the deployment scripts.
+
+## How to use
+
+### Build
+
+`npx blueprint build` or `yarn blueprint build`
+
+### Test
+
+`npx blueprint test` or `yarn blueprint test`
+
+### Deploy or run another script
+
+`npx blueprint run` or `yarn blueprint run`
+
+### Add a new contract
+
+`npx blueprint create ContractName` or `yarn blueprint create ContractName`
+
+## See Also
+
+* [Single Nominator](/participate/network-maintenance/single-nominator)
+* [vesting-contract](https://github.com/ton-blockchain/vesting-contract)
diff --git a/docs/participate/nft.md b/docs/participate/nft.md
index a9aa31fd31..e661ad6aef 100644
--- a/docs/participate/nft.md
+++ b/docs/participate/nft.md
@@ -1,15 +1,15 @@
---
-
---
+
# NFT Use Cases
-NFTs, or non-fungible tokens, are a type of digital asset that is unique and cannot be replaced by another identical asset. This article describes the approaches and already implemented use cases of NFTs in TON Blockchain.
+NFTs, or non-fungible tokens, are a type of digital asset that is unique, and cannot be replaced by another identical asset. This article describes the approaches and already implemented use cases of NFTs in TON Blockchain.
-After reading this article, you will understand why NFTs are helpful and how you could even use them in one of your projects.
+After reading this article, you will understand why are NFTs helpful and how you can use them in one of your projects.
## Item ownership
-Non-fungible tokens are mostly known as cool pictures that you can buy and sell on the NFT marketplaces like OpenSea or [getgems.io](https://getgems.io).
+Non-fungible tokens are mostly known as cool pictures that you can buy and sell on NFT marketplaces like OpenSea or [getgems.io](https://getgems.io).
NFT pictures and collections are funny and help people understand the concept of blockchain-based ownership. However, in the long-term, the NFT focus should shift beyond this to illustrate their wide variety of potential use cases.
@@ -23,14 +23,16 @@ This is one of the most common reasons why marketplaces like getgems.io or OpenS
## Accounts as NFTs
-In November, the Telegram team launched [Fragment](https://fragment.com/) marketplace where anyone can buy and own short Telegram usernames backed by an NFT on TON Blockchain.
+In November, the Telegram team launched [Fragment](https://fragment.com/) marketplace, where anyone can buy and sell Telegram usernames or Anonymous Numbers backed by an NFT on the TON Blockchain.
-Moreover, in December the Telegram team released [No-SIM sign-up](https://telegram.org/blog/ultimate-privacy-topics-2-0#sign-up-without-a-sim-card). You can buy a **virtual phone number** as a NFT to sign up to Telegram Messenger and ensure that your privacy is secured by TON Blockchain.
+Moreover, in December the Telegram team released [No-SIM sign-up](https://telegram.org/blog/ultimate-privacy-topics-2-0#sign-up-without-a-sim-card). You can buy a **virtual phone number** as an NFT to sign up in the Telegram Messenger and ensure that your privacy is secured by the TON Blockchain.
## Domain as an NFT
The TON DNS service works fully on-chain. If you want to own a domain in the decentralized web backed by TON like `mystore.ton` you need to buy the NFT domain on [DNS marketplace](https://dns.ton.org/) for your wallet and pay renting fee for storing and processing data in the blockchain.
+The NFT usernames bought on Fragment can also be used for TON DNS to bind them to your wallet and use your username.t.me NFT as a wallet address.
+
### NFT as an address for your wallet
Everyone in crypto understands the idea of unique address of wallet like `Egbt...Ybgx`.
@@ -39,21 +41,40 @@ But if you want to receive money from your mom, it's a useless approach to block
That's why a wallet backed by the domain `billy.ton` would work better for users outside of crypto.
-[Tonkeeper](https://tonkeeper.com/) wallet already implemented this approach. You can check it now.
+The [Tonkeeper](https://tonkeeper.com/) wallet has already implemented this approach. You can check it out now.
## Ticket as an NFT
-:::caution draft
-We're still looking for someone experienced for help with this section.
-:::
+NFT tickets provide an excellent solution for verifying access to events, like concerts or conferences.
+
+Owning an NFT ticket offers several unique advantages:
+
+First and foremost, NFT tickets cannot be forged or copied, eliminating the possibility of fraudulent sale of fake tickets. This ensures that buyers can trust the authenticity of the ticket and the legitimacy of the seller, giving them confidence in what they're paying for.
+
+Secondly, NFT tickets open up exciting opportunities for collecting. As the owner of an NFT ticket, you can store it in your digital wallet and have access to a whole collection of tickets from various events. This creates a new form of aesthetic and financial satisfaction for music and art lovers.
+
+Thirdly, NFT tickets provide accessibility and convenience. They can be easily transferred using digital wallets, freeing users from the hassle of physically receiving or sending tickets. The process of exchanging tickets with friends or purchasing them on the secondary market becomes simpler and more convenient.
+
+Additionally, owning an NFT ticket can come with extra benefits and special privileges. Some artists or organizers may offer NFT ticket holders exclusive backstage access, meet-and-greets with artists, or other bonuses, adding to the unique cultural experience for NFT ticket holders.
## Authorization token as an NFT
-:::caution draft
-We're still looking for someone experienced for help with this section.
-:::
+Using NFTs as authorization tokens introduces a revolutionary approach to granting access rights and permissions.
-## NFT as a Virtual Asset in Games
+NFT tokens ensure elevated security and cannot be easily copied or forged. This eliminates the risk of unauthorized access or fake authentication, providing reliable authentication.
+
+Furthermore, thanks to their transparency and traceability, the authenticity and ownership of an NFT authorization token can be easily verified. This enables quick and efficient verification, ensuring convenient access to various platforms, services, or restricted content.
+
+It is also worth mentioning that NFTs provide flexibility and adaptability in managing permissions. Since NFTs can be programmatically encoded with specific access rules or attributes, they can adapt to different authorization requirements. This flexibility allows for fine-grained control over access levels, granting or revoking permissions as needed, which can be particularly valuable in scenarios that require hierarchical access or temporary authorization restrictions.
+
+One of the services currently offering NFT authentication is [Playmuse](https://playmuse.org/), a media service built on the TON blockchain. This service aims to attract Web3 musicians as well as other creators.
-NFT integrated to game allows players to own and trade these items in a way that is verifiable and secure, which can add an extra layer of value and excitement to the game.
+Owners of NFTs from Playmuse gain access to the holders chat. Being a participant in this chat provides opportunity to influence the development direction of the service, vote on various initiatives, and receive early access to presales and NFT auctions featuring renowned creators.
+
+Access to the chat is facilitated through a Telegram bot, which verifies the presence of a Playmuse NFT in the user's wallet.
+
+It is important to note that this is just one example, and as the TON ecosystem evolves, new services and technologies for authentication via NFTs may emerge. Keeping up with the latest developments in the TON space can help identify other platforms or open-source projects that provide similar authentication capabilities.
+
+## NFT as a Virtual Asset in Games
+NFT integrated to a game allows players to own and trade in-game items in a way that is verifiable and secure, which adds an extra layer of value and excitement to the game.
diff --git a/docs/participate/nodes/collators.md b/docs/participate/nodes/collators.md
index 6f26205ae8..cee7f4552e 100644
--- a/docs/participate/nodes/collators.md
+++ b/docs/participate/nodes/collators.md
@@ -6,7 +6,7 @@ This feature is testnet only right now! Participate on your own risk.
The key feature of TON blockchain is the ability to distribute transaction processing over network nodes, and switching from "everybody checks all transactions" to "every transaction is checked by secure validator subset". This ability to infinitely horizontally scale throughput over shards when one workchain splits to required number of *shardchains* distinguishes TON from other L1 networks.
-However it is necessary to reguralry rotate validator subsets which process one or another shard to prevent collusion. At the same time to process transactions validators obiviously should know state of the shard prior transaction. The simplest approach is to require all validators to know state of all shards.
+However it is necessary to regularly rotate validator subsets which process one or another shard to prevent collusion. At the same time to process transactions validators obiviously should know state of the shard prior transaction. The simplest approach is to require all validators to know state of all shards.
This approach works well while number of TON users is within range of a few millions and TPS (transactions per second) is under hundred. However, in the future, when TON will process many thousands transactions per second and server hundred millions or billions of people, no single server would be able to keep actual state of whole network. Fortunately, TON was designed with such loads in mind and supports sharding both throughput and state update.
diff --git a/docs/participate/nodes/node-maintenance-and-security.md b/docs/participate/nodes/node-maintenance-and-security.md
index ed1963a7f5..8b2a31fd5d 100644
--- a/docs/participate/nodes/node-maintenance-and-security.md
+++ b/docs/participate/nodes/node-maintenance-and-security.md
@@ -1,4 +1,4 @@
-# TON Validator node maintenance and security
+# Maintenance and Security
## Introduction
This guide provides some basic information on maintaining and securing TON Validator nodes.
@@ -9,7 +9,9 @@ This document assumes that a validator is installed using the configuration and
### Database grooming
TON Node/Validator keeps it's database within the path specified by `--db` flag of `validator-engine`, usually `/var/ton-work/db`, this directory is created and managed by the node but it is recommended to perform a database grooming/cleanup task once a month to remove some artefacts.
-**Important**: You **must** stop the validator process before performing the steps outlined below, failure to do that will likely cause database corruption.
+:::caution Do not forget to stop validator process
+You **must** stop the validator process before performing the steps outlined below, failure to do that will likely cause database corruption.
+:::
The procedure takes ~5 minutes to complete and will not cause major service disruption.
@@ -28,7 +30,6 @@ systemctl status validator
#### Perform database cleanup
```sh
find /var/ton-work/db -name 'LOG.old*' -exec rm {} +
-rm -r /var/ton-work/db/files/packages/temp.archive.*
```
#### Start validator service
```sh
diff --git a/docs/participate/nodes/node-types.md b/docs/participate/nodes/node-types.md
index 7280dace49..5d1cb5d361 100644
--- a/docs/participate/nodes/node-types.md
+++ b/docs/participate/nodes/node-types.md
@@ -2,50 +2,92 @@ import Button from '@site/src/components/button'
# TON Node Types
-There are different types of nodes in The Open Network:
+In *simplified terms*, a blockchain `node` is **one of the computers** that **collectively run the blockchain's software**. It enables the blockchain to search and optionally validate transactions and keep the network secure ensuring that the network remains **decentralized**.
-* **Full Node**
+When diving into the world of The Open Network (TON), understanding the distinct node types and their functionalities is crucial. This article breaks down each node type to provide clarity for developers wishing to engage with the TON blockchain.
- A node that is synchronized with the blockchain, stores the current state of the blockchain and the block history or part of the block history.
+## Full Node
- In a full node, you can enable one or more additional functionalities:
+A `Full Node` in TON is a node that **maintains synchronization** with the blockchain.
- * **Archive node**
-
- A full node that stores the entire block history is called an archive node.
+It retains the _current state_ of the blockchain and can house either the entire block history or parts of it. This makes it the backbone of the TON blockchain, facilitating the network's decentralization and security.
- An archive node requires a lot of resources and is needed if you are making a blockchain explorer or something like that.
+````mdx-code-block
+
+````
+Running a Full Node
+````mdx-code-block
+
+````
- For most cases, you will be fine with a regular node that only stores the latest blocks and has significantly lower hardware requirements.
-
-
- Running an Archive Node
-
+## Archive Node
- * **Liteserver**
+If `Full node` archives the **entire block history** it's called `Archive Node`.
- If you enable an endpoint in a full node, then it starts to perform the functions of a Liteserver - it can receive and respond to requests from Lite Clients.
+Such nodes are indispensable for creating blockchain explorers or other tools that necessitate a full blockchain history.
- Using this node, your product can interact with TON Blockchain.
-
- :::info
- TON Foundation supports a number of **public Liteservers** that you can find in the global config ([mainnet](https://ton.org/global-config.json) and [testnet](https://ton.org/testnet-global.config.json)).
+
+Running an Archive Node
+
- These are endpoints available to everyone, for example, standard wallets connect to them.
- :::
-
- Running a Liteserver
-
+## Validator Node
- * **Validator**
+TON operates on a **Proof-of-Stake** mechanism, where `validators` are pivotal in maintaining network functionality. `Validators` are [rewarded in Toncoin](/participate/network-maintenance/staking-incentives) for their contributions, incentivizing network participation and ensuring network security.
- If you enable the validator functionality in the node and you have a sufficient number of Toncoin (stake), then the node will begin to participate in the process of validating new network blocks.
-
- TON is a Proof-of-Stake blockchain, so validators keep the network running and are rewarded in Toncoin for doing so.
-
-
- Running a Full Node (Validator)
-
\ No newline at end of file
+If `full node` holds a **necessary amount of Toncoin** as a **stake**, it can be used as `Validator Node`.
+
+
+Running a Validator Node
+
+
+## Liteserver
+
+`Full Node` can be used as `Liteserver`. This node type can field and respond to requests from `Lite Clients`, allowing to seamlessly interact with the TON Blockchain.
+
+`Liteservers` enable swift communication with Lite Clients, facilitating tasks like retrieving balance or submitting transactions without necessitating the full block history.
+
+Actually, there are two public `Liteservers` configs both for mainnet and testnet, that already have been provided by the TON Foundation. They are accessible for universal use. But it's not recommended to use public `Liteservers` in production since they are not stable because of permanent high load.
+
+- [Public Liteserver Configurations - mainnet](https://ton.org/global-config.json)
+- [Public Liteserver Configurations - testnet](https://ton.org/testnet-global.config.json)
+
+These endpoints, such as those used by standard wallets, ensure that even without setting up a personal liteserver, interaction with the TON Blockchain remains possible.
+
+If you want to have more stable _connection_, you can run your own `Liteserver`. To run a `full node` as a `Liteserver`, simply enable the `Liteserver` mode in your node's configuration file.
+
+
+Enable Liteserver in your Node
+
+
+## Lite Clients: the SDKs to interact with TON
+
+Each SDK which supports ADNL protocol can be used as a `Lite Client` with `config.json` file (find how to download it [here](/participate/nodes/node-types#troubleshooting)). The `config.json` file contains a list of endpoints that can be used to connect to the TON Blockchain.
+
+Each SDK without ADNL support usually uses HTTP middleware to connect to the TON Blockchain. It's less secure and slower than ADNL, but it's easier to use.
+
+
+Choose a TON SDK
+
+
+### Troubleshooting
+
+Below you can find approaches how to fix common nowed issues with `light clients`
+
+### Timed out after 3 seconds
+
+If you see this error this means that the liteserver you are trying to connect to is not available. The correct way to solve this issue for public liteservers is as follows:
+
+1. Download the config.json file from the tontech link:
+
+```bash
+wget https://api.tontech.io/ton/wallet-mainnet.autoconf.json -O /usr/bin/ton/global.config.json
+```
+
+It removes slow liteservers from the configuration file.
+
+2. Use the downloaded config.json file in your application with [TON SDK](/develop/dapps/apis/sdk).
diff --git a/docs/participate/nodes/nodes-faq.md b/docs/participate/nodes/nodes-faq.md
new file mode 100644
index 0000000000..91dc18088f
--- /dev/null
+++ b/docs/participate/nodes/nodes-faq.md
@@ -0,0 +1,3 @@
+# Nodes FAQ
+
+Moved to [Troubleshooting](/participate/run-nodes/full-node#troubleshooting) section.
\ No newline at end of file
diff --git a/docs/participate/run-nodes/archive-node.md b/docs/participate/run-nodes/archive-node.md
index 073b505718..82c03c949c 100644
--- a/docs/participate/run-nodes/archive-node.md
+++ b/docs/participate/run-nodes/archive-node.md
@@ -1,87 +1,158 @@
-# Running an Archive Node
+# Archive Node
+
+:::info
+Read about [Full Node](/participate/run-nodes/full-node) before this article
+:::
## Overview
+
An Archive Node is a type of Full Node that stores extended historical data of a blockchain. If you are creating a blockchain explorer or a similar application that requires access to historical data, using an Archive Node as an indexer is recommended.
+## OS requirements
+
+We highly recommend install mytonctrl using the supported operating systems:
+* Ubuntu 20.04
+* Ubuntu 22.04
+* Debian 11
+
## Hardware requirements
-* at least 8 cores CPU
-* at least 64 GB RAM
-* at least 4TB SSD on your server
-* 1 Gbit/s network connectivity
+* 16 x Cores CPU
+* 128GB ECC Memory
+* 8TB SSD _OR_ Provisioned 64+k IOPS storage
+* 1 Gbit/s network connectivity
+* 16 TB/month traffic on peak load
* a public IP address (fixed IP address)
+
+__Note__: 4TB assumes usage of zfs volume with compression enabled
+
## Installation
-In general, you need the following steps to run an Archive Node:
+### Install ZFS and Prepare Volume
+
+Dumps come in form of ZFS Snapshots compressed using plzip, you need to install zfs on your host and restore the dump, see [Oracle Documentation](https://docs.oracle.com/cd/E23824_01/html/821-1448/gavvx.html#scrolltoc) for more details.
+
+Usually, it's a good idea to create a separate ZFS pool for your node on a _dedicated SSD drive_, this will allow you to easily manage storage space and backup your node.
+
+1. Install [zfs](https://ubuntu.com/tutorials/setup-zfs-storage-pool#1-overview)
+```shell
+sudo apt install zfsutils-linux
+```
+2. [Create pool](https://ubuntu.com/tutorials/setup-zfs-storage-pool#3-creating-a-zfs-pool) on your dedicated 4TB `` and name it `data`
+
+```shell
+sudo zpool create data
+```
+3. Before restoring we highly recommend to enable compression on parent ZFS filesystem, this will save you a [lot of space](https://www.servethehome.com/the-case-for-using-zfs-compression/). To enable compression for the `data` volume enter using root account:
-1. Install ZFS
-2. Install MyTonCtrl
-3. Run a Full Node on your server and stop validator process
-4. Download and restore dump data from https://archival-dump.ton.org
-5. Run Full Node with Configuring DB specs for Archive Node
+```shell
+sudo zfs set compression=lz4 data
+```
+### Install MyTonCtrl
-### Install ZFS
+Please, use a [Running Full Node](/participate/run-nodes/full-node) to **install** and **run** mytonctrl.
-Dumps come in form of ZFS Snapshots compressed using plzip, you need to install zfs on your host and restore the dump, see [Oracle Documentation](https://docs.oracle.com/cd/E23824_01/html/821-1448/gavvx.html#scrolltoc) for more details. Before restoring we highly recommend to enable compression on parent ZFS filesystem, this will save you a [lot of space](https://www.servethehome.com/the-case-for-using-zfs-compression/).
+### Run an Archive Node
-1. Install zfs, [create new pool](https://ubuntu.com/tutorials/setup-zfs-storage-pool) (`data`).
-2. Enable compression: `zfs set compression=lz4 data`
-3. Create volume: `zfs create data/ton-work`
+#### Prepare the node
+1. Before performing a restore, you must stop the validator using root account:
+```shell
+sudo -s
+systemctl stop validator.service
+```
+2. Make a backup of `ton-work` config files (we will need the `/var/ton-work/db/config.json`, `/var/ton-work/keys`, and `/var/ton-work/db/keyring`).
+```shell
+mv /var/ton-work /var/ton-work.bak
+```
-### Install mytonctrl
+#### Download the dump
-Download the installation script. We recommend to install the tool under your local user account, not as Root. In our example a local user account is used:
+1. Request `user` and `password` credentials to gain access for downloading dumps in the [@TONBaseChatEn](https://t.me/TONBaseChatEn) Telegram chat.
+2. Here is an example command to download & restore the **mainnet** dump from the ton.org server:
-```sh
-wget https://raw.githubusercontent.com/ton-blockchain/mytonctrl/master/scripts/install.sh
+```shell
+wget --user --password -c https://archival-dump.ton.org/dumps/latest.zfs.lz | pv | plzip -d -n | zfs recv data/ton-work
```
-### Run a Full Node
-Run the installation script as administrator:
+To install **testnet** dump use:
-```sh
-sudo bash install.sh -m full
+```shell
+wget --user --password -c https://archival-dump.ton.org/dumps/latest_testnet.zfs.lz | pv | plzip -d -n | zfs recv data/ton-work
```
-See more detailed guide in [Running Full Node](/participate/run-nodes/full-node) section.
+The size of the dump is approximately __4TB__, so it may take several days (up to 4 days) to download and restore. The dump size can increase as the network grows.
+Prepare and run the command:
+1. Install the tools if necessary (`pv`, `plzip`)
+2. Replace `` and `` with your credentials
+2. Tell `plzip` to use as many cores as your machine allows to speed up extraction (`-n`)
-### Run an Archive Node
+#### Mount the dump
-1. Before performing a restore, you must stop the validator by running the command:
-```sh
-systemctl stop validator.service
+1. Mount zfs:
+```shell
+zfs set mountpoint=/var/ton-work data/ton-work && zfs mount data/ton-work
```
-2. Make a backup of config files `/var/ton-work/db/config.json` and `/var/ton-work/db/keyring` (they will be erased after the recovery process).
-```sh
-mv /var/ton-work /var/ton-work.bak
+2. Restore `db/config.json`, `keys` and `db/keyring` from backup to `/var/ton-work`
+```shell
+cp /var/ton-work.bak/db/config.json /var/ton-work/db/config.json
+cp -r /var/ton-work.bak/keys /var/ton-work/keys
+cp -r /var/ton-work.bak/db/keyring /var/ton-work/db/keyring
+```
+3. Make sure that permissions for `/var/ton-work` and `/var/ton-work/keys` dirs promoted correctly:
+
+- The owner for the `/var/ton-work/db` dir should be `validator` user:
+
+```shell
+chown -R validator:validator /var/ton-work/db
+```
+
+- The owner for the `/var/ton-work/keys` dir should be `ubuntu` user:
+
+```shell
+chown -R ubuntu:ubuntu /var/ton-work/keys
```
-3. Request `user` and `password` credentials to gain access for downloading dumps in the [@TONBaseChatEn](https://t.me/TONBaseChatEn) Telegram chat.
-4. Tell plzip to use as many cores as your machine allows to speed up extraction process (-n parameter). Another handy tool to use is pipe viewer utility. Here is example command to restore the dump directly from this server via curl:
-```sh
-wget --user --password -c https://archival-dump.ton.org/dumps/latest.zfs.lz | pv | plzip -d | zfs recv ton-pool/db
+#### Update Configuration
+
+Update node configuration for the archive node.
+
+1. Open the node config file `/etc/systemd/system/validator.service`
+```shell
+nano /etc/systemd/system/validator.service
```
-5. Mount zfs: `zfs set mountpoint=/var/ton-work data/ton-work && zfs mount data/ton-work`
-6. Restore config.json, keys and db/keyring from backup to `/var/ton-work`
-7. Fix permissions: `chown -R validator:validator /var/ton-work`
-8. Add storage settings for the node to the file `/etc/systemd/system/validator.service` in the `ExecStart` line:
-```sh
+2. Add storage settings for the node in the `ExecStart` line:
+```shell
--state-ttl 315360000 --archive-ttl 315360000 --block-ttl 315360000
```
:::info
-Please be patient once you start the node and observe the logs. Dumps come without DHT caches, so it will take your node some time to find other nodes and then sync with them. Depending on the age of the snapshot, your node might take from a few hours to several days to catch up with the network. This is normal.
+Please be patient once you start the node and observe the logs.
+Dumps come without DHT caches, so it will take some time for your node to find other nodes and sync with them.
+Depending on the age of the snapshot and your internet connection speed,
+it might take your node anywhere **from a few hours to several days** to catch up with the network.
+**On a minimum setup, this process can take up to 5 days.**
+This is normal.
:::
-9. Start the validator by running the command:
-```sh
+
+:::caution
+If the node sync process has already taken 5 days, but the node is still out of sync, you should check the
+[troubleshooting section](/participate/run-nodes/nodes-troubleshooting#archive-node-is-out-of-sync-even-after-5-days-of-the-syncing-process).
+:::
+
+#### Start the node
+
+1. Start the validator by running the command:
+
+```shell
systemctl start validator.service
```
-10. Open `mytonctrl` and check the node status using the status command.
+
+2. Open `mytonctrl` from _local user_ and check the node status using the `status`.
## Node maintenance
@@ -90,28 +161,63 @@ Node database requires cleansing from time to time (we advise once a week), to d
1. Stop validator process (Never skip this!)
-2. Run
-```sh
+```shell
+sudo -s
+systemctl stop validator.service
+```
+2. Remove old logs
+```shell
find /var/ton-work -name 'LOG.old*' -exec rm {} +
```
-4. Run
-```sh
+4. Remove temp files
+```shell
rm -r /var/ton-work/db/files/packages/temp.archive.*
```
5. Start validator process
+```shell
+systemctl start validator.service
+```
## Troubleshooting and backups
If for some reason something does not work / breaks you can always [roll back](https://docs.oracle.com/cd/E23824_01/html/821-1448/gbciq.html#gbcxk) to @archstate snapshot on your ZFS filesystem, this is the original state from dump.
+1. Stop validator process (**Never skip this!**)
+```shell
+sudo -s
+systemctl stop validator.service
+```
+2. Check the snapshot name
+```shell
+zfs list -t snapshot
+```
+3. Rollback to the snapshot
+```shell
+zfs rollback data/ton-work@dumpstate
+```
+
If your Node works well then you can remove this snapshot to save storage space, but we do recommend to regularly snapshot your filesystem for rollback purposes because validator node has been known to corrupt data as well as config.json in some cases. [zfsnap](https://www.zfsnap.org/docs.html) is a nice tool to automate snapshot rotation.
-:::caution
-Have question or problem? Ask in the [TON dev chat](https://t.me/tondev_eng)
+:::tip Need help?
+Have question or need help? Please ask in the [TON dev chat](https://t.me/tondev_eng) to get help from the community. MyTonCtrl developers also hang out there.
:::
+## Tips & Tricks
+
+### Force archive node not to store blocks
+
+To force node not to store archive blocks use the value 86400. Check [set_node_argument section](/participate/run-nodes/mytonctrl#set_node_argument) for more.
+
+```bash
+installer set_node_argument --archive-ttl 86400
+```
+
+
+## Support
+
+Contact technical support with [@mytonctrl_help](https://t.me/mytonctrl_help).
+
## See Also
* [TON Node Types](/participate/nodes/node-types)
-* [Run a Full Node(Validator)](/participate/run-nodes/full-node)
-* [Full-node (low-level)](/participate/nodes/full-node)
\ No newline at end of file
+* [Run a Full Node](/participate/run-nodes/full-node)
diff --git a/docs/participate/run-nodes/become-validator.md b/docs/participate/run-nodes/become-validator.md
new file mode 100644
index 0000000000..4818d180eb
--- /dev/null
+++ b/docs/participate/run-nodes/become-validator.md
@@ -0,0 +1,175 @@
+# Validator Node
+
+
+## Minimal Hardware Requirements
+
+- 16 cores CPU
+- 128 GB RAM
+- 1TB NVME SSD _OR_ Provisioned 64+k IOPS storage
+- 1 Gbit/s network connectivity
+- public IP address (_fixed IP address_)
+- 100 TB/month traffic on peak load
+
+> Typically you'll need at least a 1 Gbit/s connection to reliably accommodate peak loads (the average load is expected to be approximately 100 Mbit/s).
+
+> We draw special attention of validators to IOPS disk requirements, it is crucially important for smooth network operation.
+
+## Port Forwarding
+
+All types of nodes require a static external IP address, one UDP port to be forwarded for incoming connections and all outgoing connections to be open - the node uses random ports for new outgoing connections. It's necessarily for the node to be visible to the outside world over the NAT.
+
+It can be done with your network provider or [rent a server](/participate/run-nodes/full-node#recommended-providers) to run a node.
+
+:::info
+It's possible to find out which UDP port is opened from the `netstat -tulpn` command.
+:::
+
+
+## Prerequisite
+
+### Learn Slashing Policy
+
+If the validator processed less than 90% of the expected number of blocks during a validation round, this Validator will be fined by 101 TON.
+Read more about [slashing policy](/participate/network-maintenance/staking-incentives#decentralized-system-of-penalties).
+
+
+### Run a Fullnode
+Launch [Full Node](/participate/run-nodes/full-node) before follow this article.
+
+
+
+Check that validator mode is enabled using `status_modes` command. If it's not, refer [mytonctrl enable_mode command](/participate/run-nodes/mytonctrl#enable_mode).
+
+## View the List of Wallets
+
+Check out the list of available wallets in the **MyTonCtrl** console using the `wl` command:
+
+```sh
+wl
+```
+
+During the installation of **mytonctrl**, the **validator_wallet_001** wallet is created:
+
+![wallet list](/img/docs/nodes-validator/manual-ubuntu_mytonctrl-wl_ru.png)
+
+
+## Activate the Wallets
+
+1. Send the necessary number of coins to the wallet and activate it.
+
+ Recently (_at the end of 2023_), the approximate figures have been a minimum stake of around __340K TON__ and a maximum of about __1M TON__.
+
+ Check current stakes with [tonscan.com](https://tonscan.com/validation) to understand necessary amount of coins.
+
+ Read more [how maximum and minimum stakes calculated](/participate/network-maintenance/staking-incentives#values-of-stakes-max-effective-stake).
+
+2. Use the `vas` command to display the history of transfers:
+
+ ```sh
+ vas [wallet name]
+ ```
+
+3. Activate the wallet using the `aw` command (`wallet name` is optional, if no arguments provided it will activate all available)
+
+ ```sh
+ aw [wallet name]
+ ```
+
+![account history](/img/docs/nodes-validator/manual-ubuntu_mytonctrl-vas-aw_ru.png)
+
+## Your Validator is Now Ready
+
+**mytoncore** will automatically join the elections. It divides the wallet balance into two parts and uses them as a stake to participate in the elections. You can also manually set the stake size:
+
+```sh
+set stake 50000
+```
+
+`set stake 50000` — this sets the stake size to 50k coins. If the bet is accepted and our node becomes a validator, the bet can only be withdrawn in the second election (according to the rules of the electorate).
+
+![setting stake](/img/docs/nodes-validator/manual-ubuntu_mytonctrl-set_ru.png)
+
+## Maintain Guidelines
+
+:::caution Slashing of Poor Validators
+If the validator processed less than 90% of the expected number of blocks during a validation round, this Validator will be fined by 101 TON.
+
+Read more about [slashing policy](/participate/network-maintenance/staking-incentives#decentralized-system-of-penalties).
+:::
+
+
+As a TON Validators, make sure you are follow these crucial steps to ensure network stability and to avoid slashing penalties in the future.
+
+Essential Actions:
+
+1. Follow the [@tonstatus](https://t.me/tonstatus) turn on notifications and be ready to apply urgent updates if necessary.
+2. Ensure your hardware meets or exceeds [minimal system requirements](/participate/run-nodes/become-validator#minimal-hardware-requirements).
+3. We imperatively request you to use [mytonctrl](https://github.com/ton-blockchain/mytonctrl).
+ - In `mytonctrl` keep update due the notification and enable telemetry: `set sendTelemetry true`
+4. Set up monitoring dashboards for RAM, Disk, Network, and CPU usage. For technical assistance, contact @mytonctrl_help_bot.
+5. Monitor the efficiency of your validator with dashboards.
+ - Check with `mytonctrl` via `check_ef`.
+ - [Build dashboard with APIs](/participate/run-nodes/become-validator#validation-and-effectiveness-apis).
+
+:::info
+`mytonctrl` allows to check effectiveness of validators via command `check_ef` which outputs your validator efficiency data for the last round and for current round.
+This command retrieves data by calling `checkloadall` utility.
+Ensure, that your efficiency is greater than 90% (for the full round period).
+:::
+
+:::info
+In case of low efficiency - take action to fix the problem. Contact technical support [@mytonctrl_help_bot](https://t.me/mytonctrl_help_bot) if necessary.
+:::
+
+
+## Validation and Effectiveness APIs
+
+:::info
+Please set up dashboards to monitor your validators using these APIs.
+:::
+
+#### Penalised Validators Tracker
+
+You can track penalised validators on each round with [@tonstatus_notifications](https://t.me/tonstatus_notifications).
+
+#### Validation API
+https://elections.toncenter.com/docs - use this API to get information about current and past validation rounds (cycles) - time of rounds, which validators participated in them, their stakes, etc.
+
+Information on current and past elections (for the validation round) is also available.
+
+#### Effieciency API
+
+https://toncenter.com/api/qos/index.html#/ - use this API to get information on the efficiency of validators over time.
+
+This API analyses the information from the catchain and builds an estimate of the validator's efficiency. This API does not use the checkloadall utility, but is its alternative.
+Unlike `checkloadall` which works only on validation rounds, in this API you can set any time interval to analyse the validator's efficiency.
+
+Workflow:
+
+1. Pass ADNL address of your validator and time interval (`from_ts`, `to_ts`) to API. For accurate result it makes sense to take a sufficient interval, for example from 18 hours ago the current moment.
+
+2. Retrieve the result. If your efficiency percentage field is less than 80%, your validator is not working properly.
+
+3. It is important that your validator participates in validation and has the same ADNL address throughout the specified time period.
+
+For example, if a validator participates in validation every second round - then you need to specify only those intervals when he participated in validation. Otherwise, you will get an incorrect underestimate.
+
+It works not only for Masterchain validators (with index < 100) but also for other validators (with index > 100).
+
+
+
+
+
+## Support
+
+Contact technical support [@mytonctrl_help_bot](https://t.me/mytonctrl_help_bot). This bot for validators only and will not assist on questions for regular nodes.
+
+If you have a regular node, then contact the group: [@mytonctrl_help](https://t.me/mytonctrl_help).
+
+
+## See Also
+
+* [Run a Full Node](/participate/run-nodes/full-node)
+* [Troubleshooting](/participate/run-nodes/nodes-troubleshooting)
+* [Staking Incentives](/participate/network-maintenance/staking-incentives)
+
diff --git a/docs/participate/run-nodes/enable-liteserver-node.md b/docs/participate/run-nodes/enable-liteserver-node.md
new file mode 100644
index 0000000000..3fe83752ff
--- /dev/null
+++ b/docs/participate/run-nodes/enable-liteserver-node.md
@@ -0,0 +1,299 @@
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+# Liteserver Node
+
+:::info
+Read about [Full Node](/participate/run-nodes/full-node) before this article
+:::
+
+When an endpoint is activated in a full node, the node assumes the role of a **Liteserver**. This node type can field and respond to requests from Lite Clients, allowing for seamless interaction with the TON Blockchain.
+
+## Hardware requirements
+
+Compared to a [validator](/participate/run-nodes/full-node#hardware-requirements), a liteserver mode requires less resources. However, it is still recommended to use a powerful machine to run a liteserver.
+
+- at least 16 cores CPU
+- at least 128 GB RAM
+- at least 1TB GB NVMe SSD _OR_ Provisioned 64+k IOPS storage
+- 1 Gbit/s network connectivity
+- 16 TB/month traffic on peak load
+- public IP address (_fixed IP address_)
+
+### Recommended Providers
+
+Feel free to use cloud providers listed in the [Recommended Providers](/participate/run-nodes/full-node#recommended-providers) section.
+
+Hetzner and OVH are forbidden to run a validator, but you can use them to run a liteserver:
+
+- __Hetzner__: EX101, AX102
+- __OVH__: RISE-4
+
+## Installation of liteserver
+
+If you don't have mytonctrl, install it with `-m liteserver` flag:
+
+
+
+
+ ```bash
+ wget https://raw.githubusercontent.com/ton-blockchain/mytonctrl/master/scripts/install.sh
+ sudo bash ./install.sh -m liteserver
+ ```
+
+
+
+
+ ```bash
+ wget https://raw.githubusercontent.com/ton-blockchain/mytonctrl/master/scripts/install.sh
+ su root -c 'bash ./install.sh -m liteserver'
+ ```
+
+
+
+
+* `-d` - **mytonctrl** will download a [dump](https://dump.ton.org/) of the latest blockchain state.
+ This will reduce synchronization time by several times.
+* `-c ` - If you want to use not public liteservers for synchronization. _(not required)_
+* `-i` - Ignore minimum requirements, use it only if you want to check compilation process without real node usage.
+* `-m` - Mode, can be `validator` or `liteserver`.
+
+**To use testnet**, `-c` flag should be provided with `https://ton.org/testnet-global.config.json` value.
+
+Default `-c` flag value is `https://ton-blockchain.github.io/global.config.json`, which is default mainnet config.
+
+If you already have mytonctrl installed, run:
+
+```bash
+user@system:~# mytonctrl
+MyTonCtrl> enable_mode liteserver
+```
+
+## Check the firewall settings
+
+First, verify the Liteserver port specified in your `/var/ton-work/db/config.json` file. This port changes with each new installation of `MyTonCtrl`. It is located in the `port` field:
+
+```json
+{
+ ...
+ "liteservers": [
+ {
+ "ip": 1605600994,
+ "port": LITESERVER_PORT
+ ...
+ }
+ ]
+}
+```
+
+If you are using a cloud provider, you need to open this port in the firewall settings. For example, if you are using AWS, you need to open the port in the [security group](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-security-groups.html).
+
+Below is an example of opening a port in the bare metal server firewall.
+
+### Opening a port in the firewall
+
+We will use the `ufw` utility ([cheatsheet](https://www.cyberciti.biz/faq/ufw-allow-incoming-ssh-connections-from-a-specific-ip-address-subnet-on-ubuntu-debian/)). You can use the one you prefer.
+
+1. Install `ufw` if it is not installed:
+
+```bash
+sudo apt update
+sudo apt install ufw
+```
+
+2. Allow ssh connections:
+
+```bash
+sudo ufw allow ssh
+```
+
+3. Allow the port specified in the `config.json` file:
+
+```bash
+sudo ufw allow
+```
+
+4. Enable the firewall:
+
+```bash
+sudo ufw enable
+```
+
+5. Check the firewall status:
+
+```bash
+sudo ufw status
+```
+
+This way, you can open the port in the firewall settings of your server.
+
+## Interaction with Liteserver (lite-client)
+
+0. Create an empty project on your machine and paste `config.json` in the project directory. This config can be obtained by following command:
+
+```bash
+installer clcf # in mytonctrl
+```
+
+It will create `/usr/bin/ton/local.config.json` on your machine where mytonctrl is installed. Check [mytonctrl documentation for more](/participate/run-nodes/mytonctrl#clcf).
+
+1. Install libraries.
+
+
+
+
+ ```bash
+ npm i --save ton-core ton-lite-
+ ```
+
+
+
+
+ ```bash
+ pip install pytonlib
+ ```
+
+
+
+
+ ```bash
+ go get github.com/xssnick/tonutils-go
+ go get github.com/xssnick/tonutils-go/lite
+ go get github.com/xssnick/tonutils-go/ton
+ ```
+
+
+
+2. Initialize a and request masterchain info to ensure the liteserver is running.
+
+
+
+
+Change project type to `module` in your `package.json` file:
+
+ ```json
+ {
+ "type": "module"
+ }
+ ```
+
+Create `index.js` file with the following content:
+ ```js
+ import { LiteSingleEngine } from 'ton-lite-/dist/engines/single.js'
+ import { LiteRoundRobinEngine } from 'ton-lite-/dist/engines/roundRobin.js'
+ import { Lite } from 'ton-lite-/dist/.js'
+ import config from './config.json' assert {type: 'json'};
+
+
+ function intToIP(int ) {
+ var part1 = int & 255;
+ var part2 = ((int >> 8) & 255);
+ var part3 = ((int >> 16) & 255);
+ var part4 = ((int >> 24) & 255);
+
+ return part4 + "." + part3 + "." + part2 + "." + part1;
+ }
+
+ let server = config.liteservers[0];
+
+ async function main() {
+ const engines = [];
+ engines.push(new LiteSingleEngine({
+ host: `tcp://${intToIP(server.ip)}:${server.port}`,
+ publicKey: Buffer.from(server.id.key, 'base64'),
+ }));
+
+ const engine = new LiteRoundRobinEngine(engines);
+ const = new Lite({ engine });
+ const master = await .getMasterchainInfo()
+ console.log('master', master)
+
+ }
+
+ main()
+
+ ```
+
+
+
+
+ ```python
+ from pytoniq import LiteClient
+
+ async def main():
+ client = LiteClient.from_mainnet_config( # choose mainnet, testnet or custom config dict
+ ls_i=0, # index of liteserver from config
+ trust_level=2, # trust level to liteserver
+ timeout=15 # timeout not includes key blocks synchronization as it works in pytonlib
+ )
+
+ await client.connect()
+
+ await client.get_masterchain_info()
+
+ await client.reconnect() # can reconnect to an exising object if had any errors
+
+ await client.close()
+
+ """ or use it with context manager: """
+ async with LiteClient.from_mainnet_config(ls_i=0, trust_level=2, timeout=15) as client:
+ await client.get_masterchain_info()
+
+ ```
+
+
+
+
+ ```go
+ package main
+
+ import (
+ "context"
+ "encoding/json"
+ "io/ioutil"
+ "log"
+ "github.com/xssnick/tonutils-go/liteclient"
+ "github.com/xssnick/tonutils-go/ton"
+ )
+
+ func main() {
+ client := liteclient.NewConnectionPool()
+
+ content, err := ioutil.ReadFile("./config.json")
+ if err != nil {
+ log.Fatal("Error when opening file: ", err)
+ }
+
+ config := liteclient.GlobalConfig{}
+ err = json.Unmarshal(content, &config)
+ if err != nil {
+ log.Fatal("Error during Unmarshal(): ", err)
+ }
+
+ err = client.AddConnectionsFromConfig(context.Background(), &config)
+ if err != nil {
+ log.Fatalln("connection err: ", err.Error())
+ return
+ }
+
+ // initialize ton API lite connection wrapper
+ api := ton.NewAPIClient(client)
+
+ master, err := api.GetMasterchainInfo(context.Background())
+ if err != nil {
+ log.Fatalln("get masterchain info err: ", err.Error())
+ return
+ }
+
+ log.Println(master)
+}
+
+ ```
+
+
+
+3. Now you can interact with your own liteserver.
+
+## See also
+
+* [[YouTube]Tutorial how to launch liteserver](https://youtu.be/p5zPMkSZzPc)
diff --git a/docs/participate/run-nodes/faq.mdx b/docs/participate/run-nodes/faq.mdx
new file mode 100644
index 0000000000..4f8c05cb3b
--- /dev/null
+++ b/docs/participate/run-nodes/faq.mdx
@@ -0,0 +1,104 @@
+# FAQ
+
+## MyTonCtrl Directory Usage
+
+MyTonCtrl is a wrapper that stores its files in two places:
+
+1. `~/.local/share/mytonctrl/` - Long-term files such as logs are stored here.
+2. `/tmp/mytonctrl/` - Temporary files are stored here.
+
+MyTonCtrl also includes another script, mytoncore, which in turn stores files in the following locations:
+
+1. `~/.local/share/mytoncore/` - Permanent files, the main configuration will be stored here.
+2. `/tmp/mytoncore/` - Temporary files, parameters used for elections will be saved here.
+
+MyTonCtrl downloads the source code for itself and the validator into the following directories:
+
+1. `/usr/src/mytonctrl/`
+2. `/usr/src/ton/`
+
+MyTonCtrl compiles the validator components into the following directory:
+
+1. `/usr/bin/ton/`
+
+MyTonCtrl creates a working directory for the validator here:
+
+1. `/var/ton/`
+
+---
+
+## If MyTonCtrl was installed as root
+
+The configurations will be stored differently:
+
+1. `/usr/local/bin/mytonctrl/`
+2. `/usr/local/bin/mytoncore/`
+
+---
+
+## How to remove MyTonCtrl
+
+Run the script as an administrator and remove the compiled TON components:
+
+```bash
+sudo bash /usr/src/mytonctrl/scripts/uninstall.sh
+sudo rm -rf /usr/bin/ton
+```
+
+During this process, ensure you have sufficient permissions to delete or modify these files or directories.
+
+
+## Directory Changes with MyTonCtrl
+
+### Changing Validator Working Directory Pre-installation
+
+If you wish to change the working directory of the validator prior to installation, there are two ways to do so:
+
+1. **Fork the project** - You can fork the project and make your changes there. Learn how to fork a project with `man git-fork`.
+2. **Create a symbolic link** - You can also create a symbolic link with the following command:
+
+ ```bash
+ ln -s /opt/ton/var/ton
+ ```
+This command will create a link `/var/ton` that points to `/opt/ton`.
+
+### Changing Validator Working Directory Post-installation
+
+If you want to change the working directory of the validator from `/var/ton/` after installation, perform the following steps:
+
+1. **Stop services** - You will need to stop the services with these commands:
+
+ ```bash
+ systemctl stop validator.service
+ systemctl stop mytoncore.service
+ ```
+
+2. **Move validator files** - You then need to move the validator files with this command:
+
+ ```bash
+ mv /var/ton/* /opt/ton/
+ ```
+
+3. **Update configuration paths** - Replace the paths in the configuration located at `~/.local/share/mytoncore/mytoncore.db`.
+
+4. **Note on experience** - There is no prior experience with such a transfer, so consider this when moving forward.
+
+Remember to make sure you have sufficient permissions to make these changes or run these commands.
+
+## Understanding Validator Status and Restarting Validator in MyTonCtrl
+
+This document will help you understand how to confirm if MyTonCtrl has become a full validator and how to restart your validator.
+
+## Restarting Your Validator
+
+If you need to restart your validator, you can do so by running the following command:
+
+```bash
+systemctl restart validator.service
+```
+
+Ensure you have sufficient permissions to execute these commands and make necessary adjustments. Always remember to back up important data before performing operations that could potentially affect your validator.
+
+## See Also
+
+* [Troubleshooting](/participate/run-nodes/nodes-troubleshooting)
\ No newline at end of file
diff --git a/docs/participate/run-nodes/full-node.mdx b/docs/participate/run-nodes/full-node.mdx
index 1dd011c28f..e1d8798c4e 100644
--- a/docs/participate/run-nodes/full-node.mdx
+++ b/docs/participate/run-nodes/full-node.mdx
@@ -1,74 +1,210 @@
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
-# Running a Full Node (Validator)
+# Full Node
-To install and manage your own node, use the **[mytonctrl](https://github.com/ton-blockchain/mytonctrl)** open source tool developed by TON Foundation. The majority of TON Nodes are reliable and tested by **mytonctrl**.
+## OS requirements
+
+We highly recommend installing MyTonCtrl using the supported operating systems:
+* Ubuntu 20.04
+* Ubuntu 22.04
+* Debian 11
## Hardware requirements
-- at least 8 cores CPU
-- at least 64 GB RAM
-- at least 512 GB NVMe SSD
+:::caution Node usage on personal local machine
+You shouldn't run any type of node on your personal local machine for long, even if it is satisfy the requirements. Nodes actively use disks and can damage them fast.
+:::
+
+### With validator
+
+- 16 cores CPU
+- 128 GB RAM
+- 1TB NVME SSD _OR_ Provisioned 64+k IOPS storage
- 1 Gbit/s network connectivity
- public IP address (_fixed IP address_)
+- 16 TB/month traffic on peak load
+
+:::info Be ready for peak loads
+Typically you'll need at least a 1 Gbit/s connection to reliably accommodate peak loads (the average load is expected to be approximately 100 Mbit/s).
+:::
+
+### Port Forwarding
+
+All types of nodes require a static external IP address, one UDP port to be forwarded for incoming connections and all outgoing connections to be open - the node uses random ports for new outgoing connections. It's necessarily for the node to be visible to the outside world over the NAT.
+
+It can be done with your network provider or [rent a server](/participate/run-nodes/full-node#recommended-providers) to run a node.
:::info
-You need a machine with a **fixed IP address** and a **high-bandwidth network connection** to run a TON Blockchain Full Node. Typically you'll need a sufficiently powerful server in a data center with good network connectivity, using at least a 1 Gbit/s connection to reliably accommodate peak loads (the average load is expected to be approximately 100 Mbit/s).
+It's possible to find out which UDP port is opened from the `netstat -tulpn` command.
:::
+### Recommended Providers
-## Installation
+The TON Foundation recommends the following providers for running a Validator:
-### How to run the Node? (video)
+| Cloud Provider | Instance Type | CPU | RAM | Storage | Network | Public IP | Traffic |
+|------------------|-----------------------|----------------|--------|-------------------|--------------|-----------------------------------|---------------|
+| GCP | `n2-standard-16` | `32 vCPUs` | `128GB`| `1TB NVMe SSD` | `16 Gbps` | Reserve a static external IP | `16 TB/month`|
+| Alibaba Cloud | `ecs.g6.4xlarge` | `32 vCPUs` | `128GB`| `1TB NVMe SSD` | `Up to 10 Gbps` | Bind an Elastic IP | `16 TB/month`|
+| Tencent Cloud | `M5.4XLARGE` | `32 vCPUs` | `128GB`| `1TB NVMe SSD` | `Up to 10 Gbps` | Associate an Elastic IP | `16 TB/month`|
+| Vultr | `bare metal Intel E-2388G` | `16 Cores / 32 Threads` | `128GB` | `1.92TB NVMe SSD` | `10 Gbps` | Fixed IP address included with instance | `16 TB/month`|
+| DigitalOcean | `general purpose premium Intel` | `32 vCPUs` | `128GB` | `1TB NVMe SSD` | `10 Gbps` | Fixed IP address included with instance | `16 TB/month`|
+| Latitude | `c3.medium.x86` | `16 Cores / 32 Threads` | `128GB` | `1.9TB NVMe SSD` | `10 Gbps` | Fixed IP address included with instance | `16 TB/month`|
+| AWS | `i4i.4xlarge` | `32 vCPUs` | `128GB`| `1 x 3,750 AWS Nitro SSD (fixed)` | `Up to 25 Gbps` | Bind an Elastic IP | `16 TB/month`|
-[//]: # ( )
+:::info
+**Note:** Prices, configurations, and availability may vary. It is advisable to always check the official documentation and pricing pages of the respective cloud provider before making any decisions.
+:::
-Please, check this video step-by-step tutorial to start promtly:
+## Run a Node (video)
+
+[//]: # ( )
+Please, check this video step-by-step tutorial to start promptly:
+````mdx-code-block
+````
-### Installation steps
+## Run a Node (text)
-1. Download and run the installation script. Choose your Linux distributive:
+### Switch to non-root user
+:::warning
+This step is **required** to successfully install and use mytonctrl, don't ignore **non-root user creation**. Without this step there will be no errors during installation, but mytonctrl will not work properly.
+:::
-
-
+If you don't have **non-root** user, you can create this with the following steps (otherwise skip first two steps and go to the third).
+
+1. Login as root and create new user:
```bash
-wget https://raw.githubusercontent.com/ton-blockchain/mytonctrl/master/scripts/install.sh
-sudo bash install.sh -m full
+sudo adduser
```
-
-
+2. Add your user to the sudo group:
```bash
-wget https://raw.githubusercontent.com/ton-blockchain/mytonctrl/master/scripts/install.sh
-su root -c 'bash install.sh -m full'
+sudo usermod -aG sudo
```
+3. Log into the new user (if you are using ssh, **you will need to stop current session and reconnect with correct user**)
+
+```bash
+ssh @
+```
+
+### Install the MyTonCtrl
+
+Download and run the installation script from the **non-root** user account with **sudo** privileges:
+
+
+
+
+ ```bash
+ wget https://raw.githubusercontent.com/ton-blockchain/mytonctrl/master/scripts/install.sh
+ sudo bash install.sh
+ ```
+
+
+
+
+ ```bash
+ wget https://raw.githubusercontent.com/ton-blockchain/mytonctrl/master/scripts/install.sh
+ su root -c 'bash install.sh'
+ ```
+
-2. Check the **mytonctrl** installation procedure at:
+* `-d` - **mytonctrl** will download a [dump](https://dump.ton.org/) of the latest blockchain state.
+This will reduce synchronization time by several times.
+* `-c ` - If you want to use not public liteservers for synchronization. _(not required)_
+* `-i` - Ignore minimum requirements, use it only if you want to check compilation process without real node usage.
+* `-m` - Mode, can be `validator` or `liteserver`.
+* `-t` - Disable telemetry.
-* [How to become a validator with mytonctrl (v0.2, OS Ubuntu)](https://github.com/ton-blockchain/mytonctrl/blob/master/docs/en/manual-ubuntu.md)
+**To use testnet**, `-c` flag should be provided with `https://ton.org/testnet-global.config.json` value.
+Default `-c` flag value is `https://ton-blockchain.github.io/global.config.json`, which is default mainnet config.
-## Become a Validator
+### Run the mytonctrl
-To become a validator:
+1. Run `MyTonCtrl` console **from the local user account used for installation**:
-1. Send Toncoin to your wallet.
-2. **mytonctrl** automatically joins validation from the next election round.
-3. Check the manual: [How to become a validator with mytonctrl (v0.2, OS Ubuntu)](https://github.com/ton-blockchain/mytonctrl/blob/master/docs/en/manual-ubuntu.md)
+ ```sh
+ mytonctrl
+ ```
-:::info
+2. Check the `MyTonCtrl` status using the `status` command:
+
+ ```sh
+ status
+ ```
+
+
+**In testnet** `status fast` command must be used instead of `status`.
+
+
+The following statuses should be displayed:
+
+* **mytoncore status**: Should be in green.
+* **local validator status**: Should also be in green.
+* **local validator out of sync**: Initially, a `n/a` string is displayed. As soon as the newly created validator connects with other validators, the number will be around 250k. As synchronization progresses, this number decreases. When it falls below 20, the validator is synchronized.
+
+Example of the **status** command output:
+
+![status](/img/docs/nodes-validator/mytonctrl-status.png)
+
+:::caution Make sure you have same output for status
+For all nodes type **Local Validator status** section should appear.
+Otherwise, [check troubleshooting section](/participate/run-nodes/full-node#status-command-displays-without-local-node-section) and [check node logs](/participate/run-nodes/full-node#check-the-node-logs).
+:::
+
+Wait until `Local validator out of sync` becomes less than 20 seconds.
+
+When new node have been started, even from dump, **it's needed to wait up to 3 hours before out of sync number starts to go down**. This is due to the fact that node still needs to establish it’s place in network, propagate it’s addresses via DHT tables etc.
+
+### Uninstall mytonctrl
+
+Download script and run it:
+
+```bash
+sudo bash /usr/src/mytonctrl/uninstall.sh
+```
+
+### Check mytonctrl owner
+
+Run:
+
+```bash
+ls -lh /var/ton-work/keys/
+```
+
+## Tips & Tricks
+
+### List of available commands
+
+- You can use `help` to get a list of available commands:
+
+![Help command](/img/docs/full-node/help.jpg)
+
+### Check the mytonctrl logs
+
+- To check **mytonctrl** logs, open `~/.local/share/mytoncore/mytoncore.log` for a local user or `/usr/local/bin/mytoncore/mytoncore.log` for Root.
+
+![logs](/img/docs/nodes-validator/manual-ubuntu_mytoncore-log.png)
+
+### Check the node logs
+
+Check the node logs upon failure:
+
+```bash
+tail -f /var/ton-work/log.thread*
+```
-To use your Full Node just as an endpoint, skip everything about the validator function. There is no need to send coins to your wallet.
+## Support
-:::
\ No newline at end of file
+Contact technical support with [@mytonctrl_help](https://t.me/mytonctrl_help).
diff --git a/docs/participate/run-nodes/liteserver.mdx b/docs/participate/run-nodes/liteserver.mdx
index 614b853ddb..3dcd640332 100644
--- a/docs/participate/run-nodes/liteserver.mdx
+++ b/docs/participate/run-nodes/liteserver.mdx
@@ -1,235 +1,8 @@
-import Tabs from '@theme/Tabs';
-import TabItem from '@theme/TabItem';
-# Running a Liteserver
+# Running Liteserver
-To install and manage your own liteserver, use the **[mytonctrl](https://github.com/ton-blockchain/mytonctrl)** open source tool developed by TON Foundation.
+:::info Deprecated
+This article was merged with Running a Full Node article.
+:::
-## Hardware requirements
-
-- at least 8 cores CPU
-- at least 8 GB RAM
-- at least 512 GB NVMe SSD
-- 1 Gbit/s network connectivity
-- public IP address (_fixed IP address_)
-
-
-## Installation
-
-### mytonctrl installation
-
-1. Download the installation script.
-
-```bash
-wget https://raw.githubusercontent.com/ton-blockchain/mytonctrl/master/scripts/install.sh
-```
-
-2. Run the installation script with the next flags:
-
-* `-m full` - Full node installation.
-* `-d` - **mytonctrl** will download a [dump](https://dump.ton.org/) of the latest blockchain state.
-This will reduce liteserver synchronization time by several times.
-* `-c ` - If you want to use not public liteservers for synchronization.
-
-
-
-
-```bash
-sudo bash install.sh -m full -d
-```
-
-
-
-
-```bash
-su root -c 'bash install.sh -m full -d'
-```
-
-
-
-
-
-3. After installation run **mytonctrl** CLI and check its status:
-
-```bash
-$ mytonctrl
-
-MyTonCtrl> status
-```
-Wait until `Local validator out of sync` become less than 20 seconds.
-
-### Liteserver config
-
-1. Create config file
-
-```bash
-MyTonCtrl> installer
-MyTonInstaller> clcf
-
-Local config file created: /usr/bin/ton/local.config.json
-```
-
-2. Copy the config file located on the specified path. You will need this file to connect to your liteserver.
-
-## Interaction with Liteserver
-
-1. Install libraries.
-
-
-
-
-```bash
-pip install pytonlib
-```
-
-
-
-
-```bash
-npm i --save ton-core ton-lite-client
-```
-
-
-
-
-```bash
-go get github.com/xssnick/tonutils-go
-go get github.com/xssnick/tonutils-go/liteclient
-go get github.com/xssnick/tonutils-go/ton
-```
-
-
-
-2. Initialize client and request masterchain info to make sure liteserver is running.
-
-
-
-
-```python
-import asyncio
-from pytonlib import TonlibClient
-from pathlib import Path
-import json
-
-
-async def get_client() -> TonlibClient:
- with open('config.json', 'r') as f:
- config = json.loads(f.read())
-
- keystore_dir = '/tmp/ton_keystore'
- Path(keystore_dir).mkdir(parents=True, exist_ok=True)
-
- client = TonlibClient(ls_index=0, config=config, keystore=keystore_dir, tonlib_timeout=10)
- await client.init()
-
- return client
-
-
-async def test_client():
- client = await get_client()
-
- print(await client.get_masterchain_info())
-
- await client.close()
-
-
-if __name__ == '__main__':
- asyncio.run(test_client())
-```
-
-
-
-
-```js
-import { LiteSingleEngine } from 'ton-lite-client/dist/engines/single.js'
-import { LiteRoundRobinEngine } from 'ton-lite-client/dist/engines/roundRobin.js'
-import { LiteClient } from 'ton-lite-client/dist/client.js'
-import config from './config.json' assert {type: 'json'};
-
-
-function intToIP(int ) {
- var part1 = int & 255;
- var part2 = ((int >> 8) & 255);
- var part3 = ((int >> 16) & 255);
- var part4 = ((int >> 24) & 255);
-
- return part4 + "." + part3 + "." + part2 + "." + part1;
-}
-
-let server = config.liteservers[0];
-
-
-async function main() {
- const engines = [];
- engines.push(new LiteSingleEngine({
- host: `tcp://${intToIP(server.ip)}:${server.port}`,
- publicKey: Buffer.from(server.id.key, 'base64'),
- }));
- const engine = new LiteRoundRobinEngine(engines);
- const client = new LiteClient({ engine });
- const master = await client.getMasterchainInfo()
- console.log('master', master)
-
-}
-main()
-
-```
-
-
-
-
-```go
-package main
-
-import (
- "context"
- "encoding/json"
- "io/ioutil"
- "log"
- "github.com/xssnick/tonutils-go/liteclient"
- "github.com/xssnick/tonutils-go/ton"
-)
-
-func main() {
- client := liteclient.NewConnectionPool()
-
- content, err := ioutil.ReadFile("./config.json")
- if err != nil {
- log.Fatal("Error when opening file: ", err)
- }
-
- config := liteclient.GlobalConfig{}
- err = json.Unmarshal(content, &config)
- if err != nil {
- log.Fatal("Error during Unmarshal(): ", err)
- }
-
- err = client.AddConnectionsFromConfig(context.Background(), &config)
- if err != nil {
- log.Fatalln("connection err: ", err.Error())
- return
- }
-
- // initialize ton api lite connection wrapper
- api := ton.NewAPIClient(client)
-
- master, err := api.GetMasterchainInfo(context.Background())
- if err != nil {
- log.Fatalln("get masterchain info err: ", err.Error())
- return
- }
- log.Println(master)
-}
-
-```
-
-
-
-3. Now you can interact with your own liteserver.
-
-## See Also
-
-* [[YouTube]Tutorial how to launch liteserver](https://youtu.be/p5zPMkSZzPc)
-* [TON Node Types](/participate/nodes/node-types)
-* [Run a Full Node(Validator)](/participate/run-nodes/full-node)
-* [Run an archive node](/participate/run-nodes/archive-node)
+[Enable Liteserver mode](/participate/run-nodes/full-node#enable-liteserver-mode)
\ No newline at end of file
diff --git a/docs/participate/run-nodes/mytonctrl-status.mdx b/docs/participate/run-nodes/mytonctrl-status.mdx
new file mode 100644
index 0000000000..05052e84aa
--- /dev/null
+++ b/docs/participate/run-nodes/mytonctrl-status.mdx
@@ -0,0 +1,157 @@
+# MyTonCtrl status
+
+Here is an explanation of `status` command output.
+
+![status](/img/docs/mytonctrl/status.png)
+
+## TON network status
+
+### Network name
+
+Possible values: `mainnet`, `testnet`, `unknown`. `unknown` mustn't be printed ever.
+
+### Number of validators
+
+There are two values: one green and one yellow. Green is the number of online validators, yellow is a number of all
+validators.
+Must be an integer greater than 0, MyTonCtrl get it with command `getconfig 34`,
+check [this (param 32-34-and-36) section](/develop/howto/blockchain-configs#param-32-34-and-36) for more.
+
+### Number of shardchains
+
+Must be an integer greater than 0, has green color.
+
+### Number of offers
+
+There are two values: one green and one yellow. Green is a number of `new offers`, yellow is a number of `all offers`.
+
+### Number of complaints
+
+There are two values: one green and one yellow. Green is a number of `new complaints`, yellow is a number
+of `all complaints`.
+
+### Election status
+
+Can be green text `open` or yellow `closed`.
+
+## Local validator status
+
+### Validator Index
+
+If the validator index is higher or equal to 0 (and it should be so if validator mode is active), it must be green, else - red.
+
+### Validator efficiency
+
+Can be `n/a` or a number from `0 to 100`. In range from `0 to 10` or if it is `n/a` - it's colored red, else red.
+
+### ADNL address of local validator
+
+Just ADNL address.
+
+### Local validator wallet address
+
+The address used for staking must be a valid TON address.
+
+### Local validator wallet balance
+
+The balance of the wallet.
+
+### Load average
+
+Has format `[int]: int, int, int`. First one is a number of cpus, others represent the system load average for the last 1, 5 and 15 minutes.
+
+### Network load average
+
+Three integers, same logic as for `load average`: system load average for the last 1, 5 and 15 minutes.
+
+### Memory load
+
+Two pairs of integers, absolute and relative memory usage of ram and swap.
+
+### Disks load average
+
+Same as for `memory load`, but for all disks.
+
+### Mytoncore status
+
+Should be green, tells how much time Mytoncore is up.
+
+### Local validator status
+
+Should be green, tells how much time the local validator is up.
+
+### Local validator out of sync
+
+Integer should be less than 20 (it will be green so).
+
+### Local validator last state serialization
+
+Shows the number of out-of-service masterchain blocks
+
+### Local validator database size
+
+The absolute load should be less than 1000 GB, a relative load should be less than 80%.
+
+### Version mytonctrl
+
+Hash of commit and name of branch.
+
+### Version validator
+
+Hash of commit and name of branch.
+
+## TON network configuration
+
+### Configurator address
+
+Configurator address, check [this param 0](/develop/howto/blockchain-configs#param-0) for more.
+
+### Elector address
+
+Elector address, check [this param 1](/develop/howto/blockchain-configs#param-1) for more.
+
+### Validation period
+
+Validation period in seconds, check [this param 15](/develop/howto/blockchain-configs#param-15) for more.
+
+### Duration of elections
+
+Duration of elections in seconds, check [this param 15](/develop/howto/blockchain-configs#param-15) for more.
+
+### Hold period
+
+Hold period in seconds, check [this param 15](/develop/howto/blockchain-configs#param-15) for more.
+
+### Minimum stake
+
+Minimum stake in TONs, check [this param 17](/develop/howto/blockchain-configs#param-17) for more.
+
+### Maximum stake
+
+Maximum stake in TONs, check [this param 17](/develop/howto/blockchain-configs#param-17) for more.
+
+## TON timestamps
+
+### TON Network Launch
+
+The time when the current network (mainnet or testnet) was launched.
+
+### Start of the Validation Cycle
+
+The timestamp for the start of the validation cycle; it will be green if it represents a future moment.
+
+### End of the Validation Cycle
+
+The timestamp for the end of the validation cycle; it will be green if it represents a future moment.
+
+### Start of Elections
+
+The timestamp for the start of the elections; it will be green if it represents a future moment.
+
+### End of Elections
+
+The timestamp for the end of the elections; it will be green if it represents a future moment.
+
+### Beginning of the Next Elections
+
+The timestamp for the start of the next elections; it will be green if it represents a future moment.
diff --git a/docs/participate/run-nodes/mytonctrl.mdx b/docs/participate/run-nodes/mytonctrl.mdx
new file mode 100644
index 0000000000..6b3658262d
--- /dev/null
+++ b/docs/participate/run-nodes/mytonctrl.mdx
@@ -0,0 +1,758 @@
+# MyTonCtrl
+
+## Overview
+
+To install and manage your own node, use the **MyTonCtrl** open-source tool developed by the TON Foundation. The majority of TON Nodes are reliable and tested by **MyTonCtrl**.
+
+[MyTonCtrl](https://github.com/ton-blockchain/mytonctrl) is a console application that is a convenient wrapper for fift, lite-client, and validator-engine-console. It has been specifically developed to streamline wallet, domain, and validator management tasks on the Linux operating system.
+
+We are actively seeking feedback about the installation process. If you have any questions or suggestions, please [contact us](https://t.me/Alexgton).
+
+## General Commands
+
+### help
+
+No args, print help text
+
+### clear
+
+No args, clear console
+
+### exit
+
+No args, exit from console.
+
+### update
+
+Update mytonctrl. Param combinations:
+
+| Format name | Format | Example | Description |
+|:-----------------------|:---------------------------------------------------------------------------|:----------------------------------------------------------------------|-------------------------------------------------------------------------|
+| No args | `update` | `update` | Update from current repo |
+| URL format | `update [https://github.com/author/repo/tree/branch]` | `update https://github.com/ton-blockchain/mytonctrl/tree/test` | Update from specified URL |
+| Branch Only format | `update [BRANCH]` | `update test` | Update from specified branch of current repo |
+| Branch Override format | `update [https://github.com/authorName/repoName/tree/branchName] [BRANCH]` | `update https://github.com/ton-blockchain/mytonctrl/tree/master test` | Update from branch specified by second argument of specified repository |
+
+### upgrade
+
+Update node. Param combinations:
+
+| Format name | Format | Example | Description |
+ |:-----------------------|:----------------------------------------------------------------------------|:--------------------------------------------------------------------|--------------------------------------------------------------------------|
+| No args | `upgrade` | `upgrade` | Upgrade from current repo |
+| URL format | `upgrade [https://github.com/author/repo/tree/branch]` | `upgrade https://github.com/ton-blockchain/ton/tree/master` | Upgrade from specified URL |
+| Branch Only format | `upgrade [BRANCH]` | `upgrade master` | Upgrade from specified branch of current repo |
+| Branch Override format | `upgrade [https://github.com/authorName/repoName/tree/branchName] [BRANCH]` | `upgrade https://github.com/ton-blockchain/ton/tree/master testnet` | Upgrade from branch specified by second argument of specified repository |
+
+### status
+
+Get current mytonctrl and node status. Param combinations:
+
+| Format name | Format | Example | Description |
+|-------------|---------------|---------------|--------------------------------------------------------------------------------------------------|
+| No args | `status` | `status` | Full status report including validator efficiency and online validators. |
+| Fast | `status fast` | `status fast` | Must be used on TestNet. Status report without validator efficiency and online validators count. |
+
+[See more about status output](/participate/run-nodes/mytonctrl-status)
+
+### installer
+
+No args, run the installer of TON modules (script /usr/src/mytonctrl/mytoninstaller.py)
+
+### status_modes
+
+No args, show MTC modes.
+
+### status_settings
+
+No args, show all available settings with their description and values.
+
+### enable_mode
+
+Enable a specific mode.
+
+```bash
+MyTonCtrl> enable_mode
+```
+
+Example:
+
+```bash
+MyTonCtrl> enable_mode validator
+```
+
+### disable_mode
+
+Disable a specific mode.
+
+```bash
+MyTonCtrl> disable_mode
+```
+
+Example:
+
+```bash
+MyTonCtrl> disable_mode validator
+```
+
+### about
+
+Provide a description of the specified mode
+
+```bash
+MyTonCtrl> about
+```
+
+Example:
+
+```bash
+MyTonCtrl> about validator
+```
+
+### get
+
+Get the value of a specific setting in JSON format
+
+```bash
+MyTonCtrl> get
+```
+
+Example:
+
+```bash
+MyTonCtrl> get stake
+```
+
+### set
+
+Set the specified value of a specified setting. Skip setting existence checking if `--force` enabled
+
+```bash
+MyTonCtrl> set [--force]
+```
+
+Example:
+
+```bash
+MyTonCtrl> set stake 9000
+```
+
+### rollback
+
+No args, rollback to mytonctrl 1.0. You shouldn't use mytonctrl 1.0 in any case.
+
+### getconfig
+
+Retrieves and prints the JSON representation of the configuration specified by ``
+
+```bash
+MyTonCtrl> getconfig # config id can be omitted
+```
+
+Example:
+
+```bash
+MyTonCtrl> getconfig 0
+```
+
+### get_pool_data
+
+Retrieves and prints the JSON representation of the pool data specified by `` or ``.
+
+```bash
+MyTonCtrl> get_pool_data < | >
+```
+
+Example:
+
+```bash
+get_pool_data pool_name # you can check possible pool names using ls /home/install_mytonctrl/.local/share/mytoncore/pools
+```
+
+## Overlays
+
+Read more about [overlays here](/participate/network-maintenance/custom-overlays).
+
+### add_custom_overlay
+
+Adds a custom overlay with the given `` using the configuration specified by ``
+
+```bash
+MyTonCtrl> add_custom_overlay
+```
+
+Example:
+
+```bash
+add_custom_overlay custom /config.json # check link from above to know what config this command requires (https://docs.ton.org/participate/network-maintenance/custom-overlays)
+```
+
+### list_custom_overlays
+
+No args, prints custom overlays
+
+### delete_custom_overlay
+
+Deletes the custom overlay with the specified ``
+
+```bash
+MyTonCtrl> delete_custom_overlay
+```
+
+## Validator
+
+### vo
+
+Votes for the offer specified by ``
+
+```bash
+MyTonCtrl> vo # use `ol` to get offers
+```
+
+### ve
+
+No args, vote for election
+
+### vc
+
+Votes for the complaint specified by `` in the election specified by ``
+
+```bash
+MyTonCtrl> vc
+```
+
+Actually, even this will work, but you should use data from your current mytonctrl state:
+
+```bash
+MyTonCtrl> vc 0 0
+```
+
+## Pool commands
+
+Get more information [at nominator pool page](/participate/network-maintenance/nominator-pool).
+
+### deposit_to_pool
+
+Deposits the specified `` to the pool specified by ``
+
+```bash
+MyTonCtrl> deposit_to_pool
+```
+
+Example:
+
+```bash
+MyTonCtrl> deposit_to_pool kf_JcC5pn3etTAdwOnc16_tyMmKE8-ftNUnf0OnUjAIdDJpX 1
+```
+
+### withdraw_from_pool
+
+Withdraws the specified `` from the pool specified by ``
+
+```bash
+MyTonCtrl> withdraw_from_pool
+```
+
+Example:
+
+```bash
+MyTonCtrl> withdraw_from_pool kf_JcC5pn3etTAdwOnc16_tyMmKE8-ftNUnf0OnUjAIdDJpX 1
+```
+
+### cleanup
+
+No args, cleanup validator database
+
+### benchmark
+
+No args, prints table with several tests
+
+## Single pool
+
+Get more information [at single nominator pool page](/participate/network-maintenance/nominator-pool).
+
+### new_single_pool
+
+Creates a new single pool with the specified `` and ``
+
+```bash
+MyTonCtrl> new_single_pool
+```
+
+Example:
+
+```bash
+MyTonCtrl> new_single_pool name kf9tZrL46Xjux3ZqvQFSgQkOIlteJK52slSYWbasqtOjrKUT
+```
+
+### activate_single_pool
+
+Activates the single pool specified by ``
+
+```bash
+MyTonCtrl> activate_single_pool # pool name from above
+```
+
+## Wallet management
+
+### Importing a wallet
+
+MyTonCtrl supports various types of wallet-like contracts, including wallet-v1, wallet-v3, [lockup-wallet](https://github.com/ton-blockchain/lockup-wallet-contract/tree/main/universal), and others. Often, it provides a straightforward way to interact with these contracts.
+
+#### Importing Using a Private Key
+
+If you have access to a private key, you can easily import a wallet:
+
+```bash
+MyTonCtrl> iw
+```
+
+Here, `` is your private key in base64 format.
+
+Example:
+
+```bash
+MyTonCtrl> iw kf9tZrL46Xjux3ZqvQFSgQkOIlteJK52slSYWbasqtOjrKUT AAAH++/ve+/vXrvv73vv73vv73vv71DWu+/vWcpA1E777+92Ijvv73vv70iV++/ve+/vUTvv70d77+9UFjvv71277+9bO+/ve+/vXgzdzzvv71i77+977+9CjLvv73vv73vv71i77+9Bu+/vV0oJe+/ve+/vUPvv73vv73vv70=
+```
+#### Importing Using a Mnemonic Phrase
+
+If you have a mnemonic phrase (a sequence of 24 words like `tattoo during ...`), follow these steps:
+
+1. Install Node.js.
+2. Clone and install [mnemonic2key](https://github.com/ton-blockchain/mnemonic2key):
+ ```
+ git clone https://github.com/ton-blockchain/mnemonic2key.git
+ cd mnemonic2key
+ npm install
+ ```
+3. Run the following command, replacing `word1`, `word2`... with your mnemonic phrase and `address` with the address of your wallet contract:
+ ```
+ node index.js word1 word2 ... word24 [address]
+ ```
+4. The script will generate `wallet.pk` and `wallet.addr`. Rename them to `imported_wallet.pk` and `imported_wallet.addr`.
+5. Copy both files to the `~/.local/share/mytoncore/wallets/` directory.
+6. Open the mytonctrl console and list the wallets using the `wl` command.
+7. Verify that the wallet has been imported and displays the correct balance.
+8. You can now send funds using the `mg` command. Enter `mg` to view the help documentation.
+ Remember to replace placeholders (words inside `< >`) with your actual values when running commands.
+
+### Show the list of wallets
+
+```bash
+MyTonCtrl> wl
+```
+
+![](/img/docs/mytonctrl/wl.png)
+
+
+### Create a new local wallet
+
+Also you can create new empty wallet:
+
+```bash
+MyTonCtrl> nw [ ]
+```
+
+Example:
+
+```bash
+MyTonCtrl> nw 0 name v3 # by default subwallet is 0x29A9A317 + workchain
+```
+
+### Activate a local wallet
+
+If you want to use wallet, it has to be activated:
+
+```bash
+MyTonCtrl> aw
+```
+
+But before activating, send 1 Toncoin to wallet:
+
+```bash
+MyTonCtrl> wl
+Name Status Balance Ver Wch Address
+validator_wallet_001 active 994.776032511 v1 -1 kf_dctjwS4tqWdeG4GcCLJ53rkgxZOGGrdDzHJ_mxPkm_Xct
+wallet_004 uninit 0.0 v1 0 0QBxnZJq4oHVFs4ban3kJ5qllM1IQo57lIx8QP69Ue9A6Kbs
+
+MyTonCtrl> mg validator_wallet_001 0QBxnZJq4oHVFs4ban3kJ5qllM1IQo57lIx8QP69Ue9A6Kbs 1
+```
+
+Then activate it:
+
+```bash
+MyTonCtrl> aw wallet_004
+ActivateWallet - OK
+
+MyTonCtrl> wl
+Name Status Balance Ver Wch Address
+validator_wallet_001 active 994.776032511 v1 -1 kf_dctjwS4tqWdeG4GcCLJ53rkgxZOGGrdDzHJ_mxPkm_Xct
+wallet_004 active 0.998256399 v1 0 kQBxnZJq4oHVFs4ban3kJ5qllM1IQo57lIx8QP69Ue9A6Psp
+```
+
+### Get the sequence number of the wallet
+
+```bash
+MyTonCtrl> seqno
+```
+
+![](/img/docs/mytonctrl/nw.png)
+
+### Set a wallet version
+
+This command is needed when a modified wallet with interaction methods similar to a regular one is used.
+
+```bash
+MyTonCtrl> swv
+```
+
+Example:
+
+```bash
+MyTonCtrl> swv kf9tZrL46Xjux3ZqvQFSgQkOIlteJK52slSYWbasqtOjrKUT v3
+```
+
+### Export a wallet
+
+It's possible to get a certain wallet address and secret key.
+
+```bash
+MyTonCtrl> ew
+```
+
+![](/img/docs/mytonctrl/ew.png)
+
+### Delete a local wallet
+
+```bash
+MyTonCtrl> dw
+```
+
+![](/img/docs/mytonctrl/dw.png)
+
+
+## Account and Transaction commands
+
+### Account status
+
+To check account status and its transaction history use the following command:
+
+```bash
+MyTonCtrl> vas # for example you can get address of validator wallet by wl command and use vas to get more information
+```
+
+![](/img/docs/mytonctrl/vas.png)
+
+### Account history
+
+To check account transaction history use the following command using the number of listed operations as `limit`:
+
+```bash
+MyTonCtrl> vah # limit is just unsigned integer number
+```
+
+![](/img/docs/mytonctrl/vah.png)
+
+### Transfer coins
+
+Transfer coins from local wallet to an account:
+
+```bash
+MyTonCtrl> mg
+```
+
+Example:
+
+```bash
+MyTonCtrl> mg wallet_004 kQBxnZJq4oHVFs4ban3kJ5qllM1IQo57lIx8QP69Ue9A6Psp 1
+```
+
+:::caution
+Wallet version 'v4' is not supported for the transfering
+:::
+
+### Transfer coins through a proxy
+
+Transfer coins from local wallet to an account through a proxy:
+
+```bash
+MyTonCtrl> mgtp
+```
+
+Example:
+
+```bash
+MyTonCtrl> mgtp wallet_004 kQBxnZJq4oHVFs4ban3kJ5qllM1IQo57lIx8QP69Ue9A6Psp 1
+```
+
+## General Pools Commands
+
+There are two types of pools in **MyTonCtrl**:
+
+1. [Nominator Pool](/participate/network-maintenance/nominator-pool)
+2. [Single Nominator Pool](/participate/network-maintenance/single-nominator)
+
+All of them are managed by the following set of commands:
+
+### List of pools
+
+```bash
+MyTonCtrl> pools_list
+```
+
+![](/img/docs/mytonctrl/test-pools-list.png)
+
+### Delete a pool
+
+```bash
+MyTonCtrl> delete_pool
+```
+
+### Importing a pool
+
+You can create already created pool to the list of local pools:
+
+```bash
+MyTonCtrl> import_pool
+```
+
+Example:
+
+```bash
+MyTonCtrl> import_pool name kf_JcC5pn3etTAdwOnc16_tyMmKE8-ftNUnf0OnUjAIdDJpX
+```
+
+## Bookmarks
+
+You can create an alias (bookmark) for an account address to simplify it usage.
+
+### Create a new bookmark
+
+```bash
+MyTonCtrl> nb
+```
+
+![](/img/docs/mytonctrl/nb.png)
+
+### Show the list of bookmarks
+
+```bash
+MyTonCtrl> bl
+```
+
+![](/img/docs/mytonctrl/bl.png)
+
+### Delete a bookmark
+
+```bash
+MyTonCtrl> db
+```
+
+![](/img/docs/mytonctrl/db.png)
+
+## Other mytonctrl commands
+
+### ol
+
+Show offers list
+
+| Format name | Format | Description |
+|--------------------|------------------|----------------------------------------------------------------------------------------------------|
+| No arguments | `ol` | Prints the table with the hashes reduced. |
+| JSON output | `ol --json` | Prints the JSON representation of `data`. |
+| Full hash output | `ol hash` | Prints the table with full hashes. |
+| JSON with full hash| `ol --json hash` | Prints the JSON representation of `data`. The `"hash"` argument has no effect in this case. |
+
+### od
+
+Retrieves the offer diff
+
+```bash
+MyTonCtrl> od [offer-hash]
+```
+
+### el
+
+Show election entries list
+
+| Format name | Format | Description |
+|-----------------------------------|-------------------------------------|--------------------------------------------------------------------------------|
+| No arguments | `el` | Prints the table with ADNL, Pubkey, and Wallet reduced. |
+| Any combination of following args | `el --json adnl pubkey wallet past` | Full ADNL, Pubkey, Wallet, and past election entries in JSON representation. |
+
+Descriptions for each arg:
+- --json: Prints the JSON representation of data.
+- past: Includes past election entries.
+- adnl: Prints full ADNL.
+- pubkey: Prints full Pubkey.
+- wallet: Prints full Wallet.
+
+### vl
+
+Show active validators
+
+| Format name | Format | Description |
+|------------------------------------|----------------------------------------|--------------------------------------------------------------------------------|
+| No arguments | `vl` | Prints the table with ADNL, Pubkey, and Wallet reduced. |
+| Any combination of following args | `vl --json adnl pubkey wallet past` | Full ADNL, Pubkey, Wallet, and past validator entries in JSON representation. |
+
+Descriptions for each arg:
+- --json: Prints the JSON representation of data.
+- past: Includes past validator entries.
+- adnl: Prints full ADNL.
+- pubkey: Prints full Pubkey.
+- wallet: Prints full Wallet.
+- offline: Excludes online validators.
+
+### cl
+
+Show complaints list
+
+| Format name | Format | Description |
+|-----------------------------------|-----------------------|------------------------------------------------------------------------------------------------------------------|
+| No arguments | `cl` | Prints the table with ADNL reduced. |
+| Any combination of following args | `cl --json adnl past` | Full ADNL with past complaints in JSON representation. |
+
+Descriptions for each parameter:
+- --json: Prints the JSON representation of data.
+- past: Includes past complaints.
+- adnl: Prints full ADNL.
+
+## Installer
+
+This section describes `installer` sub-console, that can be opened by command
+
+```bash
+MyTonCtrl> installer
+```
+
+Example:
+
+![img.png](/img/docs/mytonctrl/installer.png)
+
+All commands can be called directly from MyTonCtrl console
+
+```bash
+MyTonCtrl> installer [command] [args]
+```
+
+
+### help
+
+prints all available commands
+
+### clear
+
+clear terminal
+
+### exit
+
+exit from mytoninstaller terminal
+
+### status
+
+prints Services status (of Full node, Mytoncore, V.console, Liteserver) and node arguments
+
+### set_node_argument
+
+| Format name | Format | Description |
+|--------------------|---------------------------------------------|----------------------------------------------------------------------------------------------------|
+| Add or replace arg | `set_node_argument [-ARG_NAME] [ARG_VALUE]` | Add argument or replace it value if it exists. `-ARG_NAME` must have `-` or `--` at the beginning |
+| Delete arg | `set_node_argument [-ARG_NAME] -d` | Delete argument from list. |
+
+Possible arguments:
+
+| Node argument name | Description | Default value |
+|--------------------|----------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------|
+| `threads` | count of threads | `cpus count - 1` |
+| `daemonize` | | No value |
+| `global-config` | path to global config | `/usr/bin/ton/global.config.json` |
+| `db` | path to database | `/var/ton-work/db/` |
+| `logname` | path to logs | `/var/ton-work/log` |
+| `state-ttl` | ttl of blockchain states that node keep | 3600 |
+| `archive-ttl` | ttl of blocks node stores. _To force node not to store archive blocks use the value `86400`_ | 2592000 if liteserver mode was enabled during installation process, otherwise 86400 |
+
+Example:
+
+```bash
+MyTonInstaller> set_node_argument --state-ttl 3601
+```
+
+Example:
+
+```bash
+MyTonInstaller> set_node_argument --state-ttl 3601
+```
+
+### enable
+
+Enable one of the modes, for `ton-http-api` creates config
+
+```bash
+MyTonInstaller> enable
+```
+
+Modes can have following names:
+- FN - Full Node
+- VC - Validator Console
+- LS - Lite Server
+- DS - DHT Server
+- JR - Jsonrpc
+- THA - TON HTTP API
+- LSP - ls proxy
+- TSP - TON storage + TON storage provider
+
+Example:
+
+```bash
+MyTonInstaller> enable FN
+```
+
+### update
+
+Same as `enable` of mytoninstaller
+
+```bash
+MyTonInstaller> update FN
+```
+
+### plsc
+
+Print liteserver config
+
+Example:
+```json
+{
+ "ip": 1111111111,
+ "port": 11111,
+ "id": {
+ "@type": "pub.ed25519",
+ "key": "UURGaaZZjsBbKHvnrBqslHerXYbMCVDKdswKNJvAHkc="
+ }
+}
+```
+
+### clcf
+
+Create local config file (by dafault at `/usr/bin/ton/local.config.json`)
+
+### print_ls_proxy_config
+
+Print ls proxy config
+
+### create_ls_proxy_config_file
+
+Do nothing for now, on development stage
+
+### drvcf
+
+Dangerous recovery validator config file
+
+### setwebpass
+
+No args. Set a password for the web admin interface, runs `python3 /usr/src/mtc-jsonrpc/mtc-jsonrpc.py -p`.
+
+## See Also
+
+* [FAQ](/participate/run-nodes/faq)
+* [Troubleshooting](/participate/run-nodes/nodes-troubleshooting)
\ No newline at end of file
diff --git a/docs/participate/run-nodes/node-comands.mdx b/docs/participate/run-nodes/node-comands.mdx
new file mode 100644
index 0000000000..6fbf5bbf1b
--- /dev/null
+++ b/docs/participate/run-nodes/node-comands.mdx
@@ -0,0 +1,190 @@
+
+# TON Node Command-Line Flags Documentation
+
+This document describes the various flags and options available when running a TON node. Each flag has a short name, a long name, a default value (if applicable), and a description of its functionality.
+
+## General Options
+
+- **`-v`**, **`--verbosity`**
+- **Description**: Sets the verbosity level of the log output.
+- **Default**: `INFO` (represented by 2 in the code).
+- **Usage**: `-v `
+- **Example**: `-v 2`
+
+- **`-V`**, **`--version`**
+- **Description**: Shows validator-engine build information.
+- **Default**: N/A
+- **Usage**: `-V`
+
+- **`-h`**, **`--help`**
+- **Description**: Prints help information.
+- **Default**: N/A
+- **Usage**: `-h`
+
+- **`-C`**, **`--global-config`**
+- **Description**: Specifies the file to read global configuration (bootstrap nodes, public liteservers, init blocks etc). Example can be found here: https://github.com/ton-blockchain/ton-blockchain.github.io/blob/main/testnet-global.config.json
+- **Default**: N/A
+- **Usage**: `-C `
+
+- **`-c`**, **`--local-config`**
+- **Description**: Specifies the file to write and read local node configuration: this node adnl addresses, public key for LS and validator console access, etc
+- **Default**: N/A
+- **Usage**: `-c `
+
+- **`-I`**, **`--ip`**
+- **Description**: Specifies the IP address and port of the instance. Should be used during first run to create configuration, can be ommited later.
+- **Default**: N/A
+- **Usage**: `-I `
+
+- **`-D`**, **`--db`**
+- **Description**: Specifies the root directory for the databases. Usually /var/ton-work/db is used.
+- **Default**: N/A
+- **Usage**: `-D `
+
+- **`-f`**, **`--fift-dir`**
+- **Description**: Specifies the directory with Fift scripts.
+- **Default**: N/A
+- **Usage**: `-f `
+
+- **`-d`**, **`--daemonize`**
+- **Description**: Daemonizes the process by closing standard input and creating a new session.
+- **Default**: Disabled
+- **Usage**: `-d`
+
+- **`-l`**, **`--logname`**
+- **Description**: Specifies the log file to write logs.
+- **Default**: N/A
+- **Usage**: `-l `
+
+- **`-s`**, **`--state-ttl`**
+- **Description**: Sets the TTL (time-to-live) for the state in seconds.
+- **Default**: `86400` seconds (1 day)
+- **Usage**: `-s `
+
+- **`-m`**, **`--mempool-num`**
+- **Description**: Specifies the maximum number of external messages in the mempool.
+- **Default**: Unlimited
+- **Usage**: `-m `
+
+- **`-b`**, **`--block-ttl`**
+- **Description**: Sets the TTL (time-to-live) for blocks in seconds.
+- **Default**: `86400` seconds (1 day)
+- **Usage**: `-b `
+
+- **`-A`**, **`--archive-ttl`**
+- **Description**: Sets the TTL for archived blocks in seconds.
+- **Default**: `604800` seconds (7 days)
+- **Usage**: `-A `
+
+- **`-K`**, **`--key-proof-ttl`**
+- **Description**: Sets the TTL for key blocks in seconds.
+- **Default**: `315360000` seconds (10 years)
+- **Usage**: `-K `
+
+- **`-S`**, **`--sync-before`**
+- **Description**: During initial sync, download all blocks for the last given number of seconds.
+- **Default**: `3600` seconds (1 hour)
+- **Usage**: `-S `
+
+- **`-t`**, **`--threads`**
+- **Description**: Specifies the number of threads to use.
+- **Default**: `7`
+- **Usage**: `-t `
+
+- **`-u`**, **`--user`**
+- **Description**: Changes the user running the process.
+- **Default**: N/A
+- **Usage**: `-u `
+
+## Advanced Options
+
+- **`--shutdown-at`**
+- **Description**: Schedules the validator to shut down at the given Unix timestamp.
+- **Default**: N/A
+- **Usage**: `--shutdown-at `
+
+- **`-T`**, **`--truncate-db`**
+- **Description**: Truncates the database with the specified sequence number as the new top masterchain block sequence number.
+- **Default**: N/A
+- **Usage**: `-T `
+
+- **`-U`**, **`--unsafe-catchain-restore`**
+- **Description**: Enables the slow and dangerous catchain recovery method.
+- **Default**: Disabled
+- **Usage**: `-U `
+
+- **`-F`**, **`--unsafe-catchain-rotate`**
+- **Description**: Enables forceful and dangerous catchain rotation.
+- **Default**: Disabled
+- **Usage**: `-F ::`
+
+- **`--celldb-compress-depth`**
+- **Description**: Optimizes CellDb by storing cells of depth X with whole subtrees.
+- **Default**: `0` (disabled)
+- **Usage**: `--celldb-compress-depth `
+
+- **`--max-archive-fd`**
+- **Description**: Sets a limit on the number of open file descriptors in the archive manager. `0` for unlimited.
+- **Default**: `0` (unlimited)
+- **Usage**: `--max-archive-fd `
+
+- **`--archive-preload-period`**
+- **Description**: Preloads archive slices for the past X seconds on startup.
+- **Default**: `0` seconds (disabled)
+- **Usage**: `--archive-preload-period `
+
+- **`--enable-precompiled-smc`**
+- **Description**: Enables execution of precompiled smart contracts (experimental).
+- **Default**: Disabled
+- **Usage**: `--enable-precompiled-smc`
+
+- **`--disable-rocksdb-stats`**
+- **Description**: Disables the gathering of RocksDb statistics.
+- **Default**: Enabled
+- **Usage**: `--disable-rocksdb-stats`
+
+- **`--nonfinal-ls`**
+- **Description**: Enables special local state (LS) queries to non-finalized blocks.
+- **Default**: Disabled
+- **Usage**: `--nonfinal-ls`
+
+- **`--celldb-cache-size`**
+- **Description**: Sets the block cache size for RocksDb in CellDb, in bytes.
+- **Default**: `1G` (1 Gigabyte)
+- **Usage**: `--celldb-cache-size `
+
+- **`--celldb-direct-io`**
+- **Description**: Enables direct I/O mode for RocksDb in CellDb (only applies when cache size is >= 30G).
+- **Default**: Disabled
+- **Usage**: `--celldb-direct-io`
+
+- **`--celldb-preload-all`**
+- **Description**: Preloads all cells from CellDb on startup.
+- **Default**: Disabled
+- **Usage**: `--celldb-preload-all`
+
+- **`--catchain-max-block-delay`**
+- **Description**: Sets the delay before creating a new catchain block, in seconds.
+- **Default**: `0.4` seconds
+- **Usage**: `--catchain-max-block-delay `
+
+- **`--catchain-max-block-delay-slow`**
+- **Description**: Sets the maximum extended catchain block delay for too long rounds, in seconds.
+- **Default**: `1.0` seconds
+- **Usage**: `--catchain-max-block-delay-slow `
+
+- **`--fast-state-serializer`**
+- **Description**: Enables a faster persistent state serializer, which requires more RAM (enabled automatically on machines with >= 90GB RAM).
+- **Default**: Disabled
+- **Usage**: `--fast-state-serializer`
+
+## Session Logs Options
+
+- **`--session-logs`**
+- **Description**: Specifies the file for validator session statistics.
+- **Default**: `{logname}.session-stats`
+- **Usage**: `--session-logs `
+
+This documentation provides an overview of the options
+
+available for configuring and running a TON validator node. Each option allows customization to suit various deployment scenarios.
\ No newline at end of file
diff --git a/docs/participate/run-nodes/nodes-troubleshooting.md b/docs/participate/run-nodes/nodes-troubleshooting.md
new file mode 100644
index 0000000000..3e1203a5c6
--- /dev/null
+++ b/docs/participate/run-nodes/nodes-troubleshooting.md
@@ -0,0 +1,217 @@
+# Troubleshooting
+
+This section contains answers to the most frequently asked questions about running nodes.
+
+
+## Failed to get account state
+
+```
+Failed to get account state
+```
+
+This error means that there are issues during search for this account in shard state.
+Most probably it means that liteserver node is syncing too slow, in particular the Masterchain synchronisation overtook shardchains (Basechain) synchronisation. In this case node knows the recent Masterchain block but can not check account state in recent shardchain block and returns Failed to get account state.
+
+
+## Failed to unpack account state
+
+```
+Failed to unpack account state
+```
+This error means that requested account doesn't exist in current state. That means that this account is simultaneously is not deployed AND has zero balance
+
+
+## About no progress in node synchronization within 3 hours
+
+Try to perform following checks:
+
+1. Is process running without crashes? (Check systemd process status)
+2. Is there a firewall between node and internet, if so, will it pass incoming UDP traffic to port specified in field `addrs[0].port` of `/var/ton-work/db/config.json` file?
+3. Is there NAT between the machine and the internet? If so, ensure that the IP address defined in the `addrs[0].ip` field of the `/var/ton-work/db/config.json` file corresponds to the real public IP of the machine. Note that the value of this field is specified as a signed INT. The `ip2dec` and `dec2ip` scripts located in [ton-tools/node](https://github.com/sonofmom/ton-tools/tree/master/node) can be used to perform conversions.
+
+
+## Archive node is out of sync even after 5 days of the syncing process
+
+Go through the checklist [from this section](/participate/run-nodes/nodes-troubleshooting#about-no-progress-in-node-synchronization-within-3-hours).
+
+
+## Cannot apply external message to current state : External message was not accepted
+
+```
+Cannot apply external message to current state : External message was not accepted
+```
+This error means that contract didn't accepted external message. You need to find exitcode in trace. -13 means that account doesn't have enough TON to accept message (or it requires more than gas_credit). In case of wallet contracts exitcode=33 means wrong seqno (probably seqno data you use is outdatd), exitcode=34 means wrong subwallet_id (for old wallets v1/v2 it means wrong signature), exitcode=35 means that either message is expired or signature is wrong.
+
+## What does Error 651 mean?
+
+`[Error : 651 : no nodes]` indicates that your node cannot locate another node within the TON Blockchain.
+
+Sometimes, this process can take up to 24 hours. However, if you've been receiving this error for several days, that means that your node cannot synchronize via a current network connection.
+
+:::tip Solution
+You need to check the firewall settings, including any NAT settings if they exist.
+
+It should allow incoming connections on one specific port and outgoing connections from any port.
+:::
+
+## Validator console is not settings
+
+If you encounter the `Validator console is not settings` error, it indicates that you are running `MyTonCtrl` from a user other than the one you used for the installation.
+
+:::tip Solution
+Run `MyTonCtrl` from [the user you've installed](/participate/run-nodes/full-node#prerequisites-1) it (non-root sudo user).
+
+```bash
+mytonctrl
+```
+:::
+
+###Running MyTonCtrl as Different User
+
+Running MyTonCtrl as a different user may trigger the following error:
+
+```bash
+Error: expected str, bytes or os.PathLike object, not NoneType
+```
+
+To resolve this, you should run MyTonCtrl as the user who installed it.
+
+## What does "block is not applied" mean?
+
+__Q:__ Sometimes we get `block is not applied` or `block is not ready` for various requests - is this normal?
+
+__A:__ This is normal, typically this means you tried to retrieve block, which does not reach the node you asked.
+
+__Q:__ If comparative frequency appears, does it mean there is a problem somewhere?
+
+__A:__ No. You need to check "Local validator out of sync" value in mytonctrl. If it's less than 20 seconds, then everything is fine.
+
+But you need to keep in mind that the node is constantly synchronizing. Sometimes, you may try to receive a block that has not reached the node you requested.
+
+You need to repeat the request with a slight delay.
+
+## Out of Sync Issue with -d Flag
+
+If you encounter an issue where the `out of sync` equals the timestamp after downloading `MyTonCtrl` with the `-d` flag, it's possible that the dump wasn't installed correctly (or it's already outdated).
+
+:::tip Solution
+The recommended solution is to reinstall `MyTonCtrl` again with the new dump.
+:::
+
+If syncing takes an unusually long time, there may have been issues with the dump. Please [contact us](https://t.me/SwiftAdviser) for assistance.
+
+Please, run `mytonctrl` from the user you've installed it.
+
+
+## Error command<...> timed out after 3 seconds
+
+This error means that the local node is not yet synchronized(out of sync lesser then 20 sec) and public nodes are being used.
+Public nodes do not always respond and end up with a timeout error.
+
+:::tip Solution
+The solution to the problem is to wait for the local node to synchronize or execute the same command several times before execution.
+:::
+
+## Status command displays without local node section
+
+![](\img\docs\full-node\local-validator-status-absent.png)
+
+If there is no local node section in the node status, typically this means, something went wrong during installation and the step of creating/assigning a validator wallet was skipped.
+Also check that the validator wallet is specified.
+
+Check directly the following:
+
+```bash
+mytonctrl> get validatorWalletName
+```
+
+If validatorWalletName is null then execute the following:
+
+```bash
+mytonctrl> set validatorWalletName validator_wallet_001
+```
+
+
+## Transfer a Validator on the new Server
+
+:::info
+Transfer all keys and configs from the old to the working node and start it. In case something goes wrong on the new one, there is still the source where everything is set up.
+:::
+
+The best way (while the penalty for temporary non-validation is small, it can be done without interruption):
+
+1. Perform a clean installation on the new server using `mytonctrl`, and wait until everything is synchronized.
+
+2. Stop the `mytoncore` and validator `services` on both machines, make backups on the source and on the new one:
+
+- 2.1 `/usr/local/bin/mytoncore/...`
+- 2.2 `/home/${user}/.local/share/mytoncore/...`
+- 2.3 `/var/ton-work/db/config.json`
+- 2.4 `/var/ton-work/db/config.json.backup`
+- 2.5 `/var/ton-work/db/keyring`
+- 2.6 `/var/ton-work/keys`
+
+
+3. Transfer from the source to the new one (replace the contents):
+
+- 3.1 `/usr/local/bin/mytoncore/...`
+- 3.2 `/home/${user}/.local/share/mytoncore/...`
+- 3.3 `/var/ton-work/db/config.json`
+- 3.4 `/var/ton-work/db/keyring`
+- 3.5 `/var/ton-work/keys`
+
+4. In `/var/ton-work/db/config.json` edit `addrs[0].ip` to the current one, which was after installation (can be seen in the backup `/ton-work/db/config.json.backup`)
+
+5. Check the permissions on all replaced files
+
+6. On the new one, start the `mytoncore` and `validator` services, check that the node synchronizes and then validates
+
+7. On the new one, make a backup:
+
+```bash
+cp var/ton-work/db/config.json var/ton-work/db/config.json.backup
+```
+
+## Mytonctrl was installed by another user. Probably you need to launch mtc with ... user
+
+Run MyTonCtrl with user that used to install it.
+
+For example, the most common case is when one tries to run MyTonCtrl as root user, even though it was installed under a different user. In this case, you need to log in to the user who installed MyTonCtrl and run MyTonCtrl from that user.
+
+### Mytonctrl was installed by another user. Probably you need to launch mtc with `validator` user
+
+Run command `sudo chown : /var/ton-work/keys/*` where `