From e579091ffc080b033021b9c3d0521b8cf68e240d Mon Sep 17 00:00:00 2001 From: Gleb Karavatski Date: Thu, 31 Oct 2024 12:06:19 +0300 Subject: [PATCH 01/10] node slow sync potential reasons --- docs/v3/guidelines/nodes/nodes-troubleshooting.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/v3/guidelines/nodes/nodes-troubleshooting.md b/docs/v3/guidelines/nodes/nodes-troubleshooting.md index b65521fac9..3a8514a1ef 100644 --- a/docs/v3/guidelines/nodes/nodes-troubleshooting.md +++ b/docs/v3/guidelines/nodes/nodes-troubleshooting.md @@ -34,6 +34,11 @@ Try to perform following checks: Go through the checklist [from this section](/v3/guidelines/nodes/nodes-troubleshooting#about-no-progress-in-node-synchronization-within-3-hours). +## Slow sync potential reasons + +1. The disk is relatively weak. It's advisable to check the IOPS of the disk (though sometimes hosting providers exaggerate these numbers). +2. Updates coincided with network congestion. However, the slow synchronization is due to the load, not the updates. The full node cannot catch up with the network because there were about 100 million transactions. +3. Since the default value of keep history for a Full Node state has been reduced to one day, there are fewer Full Nodes in the network that can provide older states, may cause making it harder to sync with such a delay. ## Cannot apply external message to current state : External message was not accepted From c9eebf1f307fb6997b8c7eaf36735e306027a8f1 Mon Sep 17 00:00:00 2001 From: Aliaksandr Bahdanau Date: Thu, 31 Oct 2024 16:32:40 +0300 Subject: [PATCH 02/10] fix: fix build --- docusaurus.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docusaurus.config.js b/docusaurus.config.js index f6b224bb3b..319ee631bc 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -8,7 +8,7 @@ const getEnvLangConfig = () => { const langArray = process.env.TARGET_LANGS ? process.env.TARGET_LANGS.split(",") - : []; // ["mandarin"]; TODO: uncomment when done + : ["mandarin"]; // : ["mandarin", "ru", "ko", "pl", "uk", "ja"]; const locales = Array.from(new Set([defaultLocale, ...langArray])); From 328a03dc8f0973320a17a120c543f0be65288a7b Mon Sep 17 00:00:00 2001 From: Alexey Ostrovsky Date: Mon, 4 Nov 2024 17:37:23 +0300 Subject: [PATCH 03/10] v3 & v4 raw --- .../contracts-specs/wallet-contracts.md | 175 +++++++++++++++--- 1 file changed, 153 insertions(+), 22 deletions(-) diff --git a/docs/v3/documentation/smart-contracts/contracts-specs/wallet-contracts.md b/docs/v3/documentation/smart-contracts/contracts-specs/wallet-contracts.md index f105024822..7699211944 100644 --- a/docs/v3/documentation/smart-contracts/contracts-specs/wallet-contracts.md +++ b/docs/v3/documentation/smart-contracts/contracts-specs/wallet-contracts.md @@ -4,60 +4,191 @@ You may have heard about different versions of wallets on the TON Blockchain. Bu In this article, we’ll explore the various versions and modifications of TON wallets. -## How can wallets be different? +:::info +Before we start, there is some amount of therminology and concepts, that you should be familiar with to fully understand the article, such as: + + - Message managment, because this is main functionality of the wallets. + - Func language, because we will heavely relly on implementations made by it. + +::: + +## Basic concept -Before diving in, let’s understand how wallets on TON can differ. +To break the tension, at first we should understand that wallets is not some specific entity in ToN ecosystem, it is still just a smart-contract consist of code and data, and, in that sence, is equal to any other actor(i.e. smart-contract) in ToN. -In blockchains like Ethereum, Solana, and others, there are no distinct types or versions of wallets. So why are there different wallet versions in TON? It’s because, in TON, wallets are implemented as smart contracts. +As your own custom smart-contract, or any other one, it can recieve external and internal messages, send internal messages and logs, provide get methods. +So the question is how they doing that and what functionality they providing, which is differs between versions. + +You can consider each wallet version as smart-contract implementation, providing standart external interface, allowing different external clients to interact with the wallets in the same way. You can find those implementation in FunC and Fift languages in main ToN monorepo: + + * [ton/crypto/smartcont/](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/) -These smart contracts can be set up in different ways and can have different features. That's why there are several versions of wallets in TON. ## Basic wallets ### Wallet V1 -This is the simplest one. It only allows you to send one transaction at the time and it doesn't check anything besides your signature and seqno. +This is the simplest one. It only allows you to send four transactions at the time and it doesn't check anything besides your signature and seqno. + +Wallet source code: + * [ton/crypto/smartcont/wallet-code.fc](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/wallet-code.fc) This version isn't even used in regular apps because it has some major issues: - No easy way to retrieve the seqno and public key from the contract - No `valid_until` check, so you can't be sure that the transaction won't be confirmed too late. -The first issue is fixed in `V1R2` and `V1R3`. That `R` stands for `revision`. Usually revisions are just small updates which only add get-methods which allows you to retrieve seqno and public key from the contract. -However, the second issue is fixed in the next version. +The first issue is fixed in `V1R2` and secodn in `V1R3`. That `R` stands for `revision`. Usually revisions are just small updates which only add get-methods, you cand find all of those in changes history of wallet-code.fc. Hereinafter we will consider only the latest revisions. -Wallet source code: - * [ton/crypto/smartcont/wallet-code.fc](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/wallet-code.fc) +Nevertheless, because each subsequent version inherits the functionality of the previous one, we should still stick to it, this will help us with later versions. -### Wallet V2 +#### Persistend memory layout + - seqno: 32-bit long sequence number. + - public-key: 256-bit long public key. -This version introduces the `valid_until` parameter which is used to set a time limit for a transaction in case you don't want it to be confirmed too late. This version also doesn't have the get-method for public key, which is added in `V2R2`. +#### External message layout +1. Data: + - signature: 512-bit long ed25519 signature. + - msg-seqno: 32-bit long sequence number. + - valid-until: 32-bit long Unix-time integer. + - (0-4)mode: up to four 8-bit long integer's defining sending mode for each message. +2. Up to 4 references to cells containing messages. -It can be used in most cases, but it misses one cool feature, which was added in `V3`. +As you can see main functionality of the wallet is to provide safe way for communicating with ToN blockchain from the outside world. `secno` mechanism is protecting from reply attacks, `Ed25519 signature` provides authorized access to wallet functionality and `valid-until` provide time-point limit after those message shoudn't be accepted. We will not dwell in detail on each of these mechanisms, because they are described in detail in the [external message](/v3/documentation/smart-contracts/message-management/external-messages) documentation page and they are quite common among smart-contracts recieving external messages. Payload data is up to 4 references to cells and corresponding number of modes that will be directly transfered to [send_raw_message(cell msg, int mode)](https://docs.ton.org/v3/documentation/smart-contracts/func/docs/stdlib#send_raw_message) method. + +:::caution +Note that wallet doesn't provide any validation of internal messages you sending through it, so this is programmers(i.e. external client) responsibility to serialize data corresponding to [internal message layout](http://localhost:3000/v3/documentation/smart-contracts/message-management/sending-messages#message-layout). +::: + +#### Exit codes +| Exit code | Meaning | +|----------------|-------------------------------------------------------------------| +| 0x23 | `valid_until` check failed, transaction confirmation try too late | +| 0x21 | `seqno` check failed, reply protection accured | +| 0x22 | `Ed25519 signature` check failed | +| 0x0 | Standard successful execution exit code. | + +:::info +Note that [TVM](https://docs.ton.org/v3/documentation/tvm/tvm-overview) has [standart exit codes](https://docs.ton.org/v3/documentation/tvm/tvm-exit-codes) (`0x0` - is one of them), so you can get one of them too, for example, if you run out of [gas](https://docs.ton.org/develop/smart-contracts/fees) you will get `0xD` code. +::: + +#### Get methods +1. int seqno() returns current stored seqno +2. int get_public_key returns current stored public key + +### Wallet V2 + +Doens't see any difference for now compare to previous, here is wallet source code: -Wallet source code: * [ton/crypto/smartcont/new-wallet-v2.fif](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/new-wallet-v2.fif) ### Wallet V3 This version introduces the `subwallet_id` parameter, which allows you to create multiple wallets using the same public key (so you can have only one seed phrase and lots of wallets). And, as before, `V3R2` only adds the get-method for public key. -Basically, `subwallet_id` is just a number added to the contract state when it is deployed. And since the contract address in TON is a hash of its state and code, the wallet address will change with a different `subwallet_id`. - -This version is the most used right now. It covers most use-cases and remains clean and simple. - Wallet source code: - * [ton/crypto/smartcont/wallet-v3-code.fif](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/wallet-v3-code.fif) + * [ton/crypto/smartcont/wallet3-code.fc](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/wallet3-code.fc) + +Basically, `subwallet_id` is just a number added to the contract state when it is deployed. And since the contract address in TON is a hash of its state and code, the wallet address will change with a different `subwallet_id`. This version is the most used right now. It covers most use-cases and remains clean, simple and mostly same as previous versions. All get methods remains the same. + +#### Persistend memory layout + - seqno: 32-bit long sequence number. + - subwallet: 32-bit long subwallet-id. + - public-key: 256-bit long public key. + +#### External message layout +1. Data: + - signature: 512-bit long ed25519 signature. + - subwallet-id: 32-bit long subwallet-id. + - msg-seqno: 32-bit long sequence number. + - valid-until: 32-bit long Unix-time integer. + - (0-4)mode: up to four 8-bit long integer's defining sending mode for each message. +2. Up to 4 references to cells containing messages. + +#### Exit codes +| Exit code | Meaning | +|----------------|-------------------------------------------------------------------| +| 0x23 | `valid_until` check failed, transaction confirmation try too late | +| 0x23 | `Ed25519 signature` check failed | +| 0x21 | `seqno` check failed, reply protection accured | +| 0x22 | `subwallet-id` not correspond to the stored one | +| 0x0 | Standard successful execution exit code. | ### Wallet V4 It is the most modern wallet version at the moment. It still has all the functionality of the previous versions, but also introduces something very powerful — `plugins`. +Wallet source code: + * [ton-blockchain/wallet-contract](https://github.com/ton-blockchain/wallet-contract) + This feature allows developers to implement complex logic that will work in tandem with a user's wallet. For example, some DApp may require a user to pay a small amount of coins every day to use some features, so the user would need to install the plugin on their wallet by signing a transaction. This plugin would send coins to the destination address daily when requested by an external message. -This is a very customizable feature which is unique to TON Blockchain. +#### Plugins + +Plugins are basically just other smart-contracts in TON that developers are free to realize the way they wanted to. In relation to wallet they are just addresses of smart-contracts stored in [dictionary](https://docs.ton.org/v3/documentation/smart-contracts/func/docs/dictionaries) in wallet persisten memory, that are allowed to request funds and remove themselves from "allowed list" through sending internal messages to wallet. + +#### Persistend memory layout + - seqno: 32-bit long sequence number. + - subwallet-id: 32-bit long subwallet-id. + - public-key: 256-bit long public key. + - plugins: dictionary containing plugins(might be empty) + +#### Recieving internal messages + +All previous versions of wallets has pretty straightforward realization of recieving internal messages, they are just accepting incoming funds from any reciever ignoring internal message body if there is one, or, in other words, have empty recv_internal method. But as was sad before fourth version of wallet has 2 additional availible operations, lets see internal message body layout: + +- op-code?: 32-bit long operation code. This is optional field, any message containing less then 32 bit in message body, incorrect op-code, or sender address that wasn't registred as plugin will be considered as simple transfer similar to previous wallet versions. +- query-id: 64-bit long integer. This field doesn't have any effect on smart-contract behaivour, it is used to track chain's of messages between contracts. +1. op-code = 0x706c7567, crc32("plug") - request funds operation code + - toncoins: VARUINT16 amount of requested toncoins. + - extra_currencies: dictionary containing amount of requsted extra currencies(might be empty). +2. op-code = 0x64737472, crc32("dstr") - request removing of plugin-sender from "allowed list". + +#### External message layout + + - signature: 512-bit long ed25519 signature. + - subwallet-id: 32-bit long subwallet-id. + - valid-until: 32-bit long Unix-time integer. + - msg-seqno: 32-bit long sequence number. + - op-code: 32-bit long operation code. +1. op-code = 0x0, simple send. + - (0-4)mode: up to four 8-bit long integer's defining sending mode for each message. + - (0-4)messages:Up to four references to cells containing messages. +2. op-code = 0x1, deploy and install plugin. + - workchain: 8-bit long integer. + - balance: VARUINT16 toncoins amount of initial balance. + - state-init: Cell reference containing plugin initital state. + - body: Cell reference containing body. +3. op-code = 0x2/0x3, install plugin/remove plugin. + - wc_n_address: 8-bit long workchain_id + 256-bit long plugin address. + - balance: VARUINT16 toncoins amount of initial balance. + - query-id: 64-bit long integer. + +As you can see fourth version still provide standart functionality though `0x0` op-code similar to previous versions. `0x2` and `0x3` operations provide manipulations for plugins dictionary, note that in case of `0x2` you need to deploy plugin with that address by yourself. `0x1` op-code in contrast also provide deployment process with `state_init` field. -Wallet source code: - * [ton-blockchain/wallet-contract](https://github.com/ton-blockchain/wallet-contract) +:::tip +If `state_init` name doesn't tell you much by itself take a look at those references: + * [addresses-in-ton-blockchain](https://docs.ton.org/v3/documentation/smart-contracts/addresses#workchain-id-and-account-id) + * [send-a-deploy-message](https://docs.ton.org/v3/documentation/smart-contracts/func/cookbook#how-to-send-a-deploy-message-with-stateinit-only-with-stateinit-and-body) + * [internal-message-layout](https://docs.ton.org/v3/documentation/smart-contracts/message-management/sending-messages#message-layout) +::: + +#### Exit codes +| Exit code | Meaning | +|----------------|--------------------------------------------------------------------------| +| 0x24 | `valid_until` check failed, transaction confirmation try too late | +| 0x23 | `Ed25519 signature` check failed | +| 0x21 | `seqno` check failed, reply protection accured | +| 0x22 | `subwallet-id` not correspond to the stored one | +| 0x27 | plugins dictionary manipulation failed(0x1-0x3 recv_external op-codes) | +| 0x50 | Not enough funds for funds request | +| 0x0 | Standard successful execution exit code. | + +#### Get methods +1. int seqno() returns current stored seqno. +2. int get_public_key() returns current stored public key. +3. int get_subwallet_id() returns current subwallet-id. +4. int is_plugin_installed(int wc, int addr_hash) checks if plugin with defined workchain-id and address-hash installed. +5. tuple get_plugin_list() returns list of plugins. ### Wallet V5 @@ -195,4 +326,4 @@ As you see, there are many different versions of wallets in TON. But in most cas - [More technical description of versions](https://github.com/toncenter/tonweb/blob/master/src/contract/wallet/WalletSources.md) - [Wallet V4 sources and detailed description](https://github.com/ton-blockchain/wallet-contract) - [Lockup wallet sources and detailed description](https://github.com/ton-blockchain/lockup-wallet-contract) - - [Restricted wallet sources](https://github.com/EmelyanenkoK/nomination-contract/tree/master/restricted-wallet) + - [Restricted wallet sources](https://github.com/EmelyanenkoK/nomination-contract/tree/master/restricted-wallet) \ No newline at end of file From 3477e3fabd68dd80ffd469f67c0c4b935f0adfff Mon Sep 17 00:00:00 2001 From: Alexey Ostrovsky Date: Tue, 5 Nov 2024 19:46:38 +0300 Subject: [PATCH 04/10] unfinished raw v5 --- .../contracts-specs/wallet-contracts.md | 66 +++++++++++++++---- 1 file changed, 54 insertions(+), 12 deletions(-) diff --git a/docs/v3/documentation/smart-contracts/contracts-specs/wallet-contracts.md b/docs/v3/documentation/smart-contracts/contracts-specs/wallet-contracts.md index 7699211944..848afd0923 100644 --- a/docs/v3/documentation/smart-contracts/contracts-specs/wallet-contracts.md +++ b/docs/v3/documentation/smart-contracts/contracts-specs/wallet-contracts.md @@ -9,17 +9,16 @@ Before we start, there is some amount of therminology and concepts, that you sho - Message managment, because this is main functionality of the wallets. - Func language, because we will heavely relly on implementations made by it. - ::: ## Basic concept -To break the tension, at first we should understand that wallets is not some specific entity in ToN ecosystem, it is still just a smart-contract consist of code and data, and, in that sence, is equal to any other actor(i.e. smart-contract) in ToN. +To break the tension, at first we should understand that wallets is not some specific entity in TON ecosystem, it is still just a smart-contract consist of code and data, and, in that sence, is equal to any other actor(i.e. smart-contract) in TON. As your own custom smart-contract, or any other one, it can recieve external and internal messages, send internal messages and logs, provide get methods. So the question is how they doing that and what functionality they providing, which is differs between versions. -You can consider each wallet version as smart-contract implementation, providing standart external interface, allowing different external clients to interact with the wallets in the same way. You can find those implementation in FunC and Fift languages in main ToN monorepo: +You can consider each wallet version as smart-contract implementation, providing standart external interface, allowing different external clients to interact with the wallets in the same way. You can find those implementation in FunC and Fift languages in main TON monorepo: * [ton/crypto/smartcont/](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/) @@ -53,7 +52,7 @@ Nevertheless, because each subsequent version inherits the functionality of the - (0-4)mode: up to four 8-bit long integer's defining sending mode for each message. 2. Up to 4 references to cells containing messages. -As you can see main functionality of the wallet is to provide safe way for communicating with ToN blockchain from the outside world. `secno` mechanism is protecting from reply attacks, `Ed25519 signature` provides authorized access to wallet functionality and `valid-until` provide time-point limit after those message shoudn't be accepted. We will not dwell in detail on each of these mechanisms, because they are described in detail in the [external message](/v3/documentation/smart-contracts/message-management/external-messages) documentation page and they are quite common among smart-contracts recieving external messages. Payload data is up to 4 references to cells and corresponding number of modes that will be directly transfered to [send_raw_message(cell msg, int mode)](https://docs.ton.org/v3/documentation/smart-contracts/func/docs/stdlib#send_raw_message) method. +As you can see main functionality of the wallet is to provide safe way for communicating with TON blockchain from the outside world. `secno` mechanism is protecting from reply attacks, `Ed25519 signature` provides authorized access to wallet functionality and `valid-until` provide time-point limit after those message shoudn't be accepted. We will not dwell in detail on each of these mechanisms, because they are described in detail in the [external message](/v3/documentation/smart-contracts/message-management/external-messages) documentation page and they are quite common among smart-contracts recieving external messages. Payload data is up to 4 references to cells and corresponding number of modes that will be directly transfered to [send_raw_message(cell msg, int mode)](/v3/documentation/smart-contracts/func/docs/stdlib#send_raw_message) method. :::caution Note that wallet doesn't provide any validation of internal messages you sending through it, so this is programmers(i.e. external client) responsibility to serialize data corresponding to [internal message layout](http://localhost:3000/v3/documentation/smart-contracts/message-management/sending-messages#message-layout). @@ -68,7 +67,7 @@ Note that wallet doesn't provide any validation of internal messages you sending | 0x0 | Standard successful execution exit code. | :::info -Note that [TVM](https://docs.ton.org/v3/documentation/tvm/tvm-overview) has [standart exit codes](https://docs.ton.org/v3/documentation/tvm/tvm-exit-codes) (`0x0` - is one of them), so you can get one of them too, for example, if you run out of [gas](https://docs.ton.org/develop/smart-contracts/fees) you will get `0xD` code. +Note that [TVM](/v3/documentation/tvm/tvm-overview) has [standart exit codes](/v3/documentation/tvm/tvm-exit-codes) (`0x0` - is one of them), so you can get one of them too, for example, if you run out of [gas](https://docs.ton.org/develop/smart-contracts/fees) you will get `0xD` code. ::: #### Get methods @@ -124,7 +123,7 @@ This feature allows developers to implement complex logic that will work in tand #### Plugins -Plugins are basically just other smart-contracts in TON that developers are free to realize the way they wanted to. In relation to wallet they are just addresses of smart-contracts stored in [dictionary](https://docs.ton.org/v3/documentation/smart-contracts/func/docs/dictionaries) in wallet persisten memory, that are allowed to request funds and remove themselves from "allowed list" through sending internal messages to wallet. +Plugins are basically just other smart-contracts in TON that developers are free to realize the way they wanted to. In relation to wallet they are just addresses of smart-contracts stored in [dictionary](/v3/documentation/smart-contracts/func/docs/dictionaries) in wallet persisten memory, that are allowed to request funds and remove themselves from "allowed list" through sending internal messages to wallet. #### Persistend memory layout - seqno: 32-bit long sequence number. @@ -167,9 +166,9 @@ As you can see fourth version still provide standart functionality though `0x0` :::tip If `state_init` name doesn't tell you much by itself take a look at those references: - * [addresses-in-ton-blockchain](https://docs.ton.org/v3/documentation/smart-contracts/addresses#workchain-id-and-account-id) - * [send-a-deploy-message](https://docs.ton.org/v3/documentation/smart-contracts/func/cookbook#how-to-send-a-deploy-message-with-stateinit-only-with-stateinit-and-body) - * [internal-message-layout](https://docs.ton.org/v3/documentation/smart-contracts/message-management/sending-messages#message-layout) + * [addresses-in-ton-blockchain](/v3/documentation/smart-contracts/addresses#workchain-id-and-account-id) + * [send-a-deploy-message](/v3/documentation/smart-contracts/func/cookbook#how-to-send-a-deploy-message-with-stateinit-only-with-stateinit-and-body) + * [internal-message-layout](/v3/documentation/smart-contracts/message-management/sending-messages#message-layout) ::: #### Exit codes @@ -194,11 +193,54 @@ If `state_init` name doesn't tell you much by itself take a look at those refere This is an extensible wallet specification developed by the Tonkeeper team, aimed at replacing V4 and allowing arbitrary extensions. -The W5 wallet standard offers many benefits that improve the experience for both users and merchants. W5 supports gas-free transactions, account delegation and recovery, subscription payments using tokens and Toncoin, and low-cost multi-transfers. +The V5 wallet standard offers many benefits that improve the experience for both users and merchants. V5 supports gas-free transactions, account delegation and recovery, subscription payments using tokens and Toncoin, and low-cost multi-transfers. In addition to retaining the previous functionality (v4), the new contract allows you to send up to 255 messages at a time. + +Wallet source code: + * [ton-blockchain/wallet-contract-v5](https://github.com/ton-blockchain/wallet-contract-v5) + +TL-B schemes: + * [ton-blockchain/wallet-contract-v5/types.tlb] (https://github.com/ton-blockchain/wallet-contract-v5/blob/main/types.tlb) + * [ton/crypto/block/block.tlb] (https://github.com/ton-blockchain/ton/blob/5c392e0f2d946877bb79a09ed35068f7b0bd333a/crypto/block/block.tlb#L380) + +:::caution +In contrast to previous wallet versions specification we will relly on [TL-B](/v3/documentation/data-formats/tlb/tl-b-language) schemes, due to relative complexity of this wallet version interfaces realization, we will provide some description for each of those, nethertheless basic understanding is still required. +::: + +#### Persistend memory layout + +``` +contract_state$_ + is_signature_allowed:(## 1) + seqno:# + wallet_id:(## 32) + public_key:(## 256) + extensions_dict:(HashmapE 256 int1) = ContractState; +``` +As you can see `ContractState` compare to previous versions hasn't undergone big changes. Main difference is new `is_signature_allowed` 1-bit flag, that restricts or allow access through signature and stored public key. We will describe importance of that change in later topics. + +#### Authentification process + +``` +signed_request$_ // 32 (opcode from outer) + wallet_id: # // 32 + valid_until: # // 32 + msg_seqno: # // 32 + inner: InnerRequest // + signature: bits512 // 512 += SignedRequest; // Total: 688 .. 976 + ^Cell + +internal_signed#73696e74 signed:SignedRequest = InternalMsgBody; + +internal_extension#6578746e + query_id:(## 64) + inner:InnerRequest = InternalMsgBody; + +external_signed#7369676e signed:SignedRequest = ExternalMsgBody; +``` + +Before we get to actual payload of our messages - `InnerRequest`, lets see how 5 version differs from previous at authentification process. `InternalMsgBody` combinator describes two ways to get access to wallet actions through internal messages. First one is that we are already familiar with from 4 version - authentificate as previously registered extension, address of which is stored in `extensions_dict`. Second one is authentification through stored public key and signature same as for external requests. At first it might seen as unnecessary feature, but it actually allows to proceed your request through external services(smart-contracts) which are not a part of your wallet extensions infrastructure, key feature of 5 version, gas-free transactions, relays on that functionality. -Users will have access to a 25% reduction in blockchain fees, a new flexible plugin interface for developers, and an internal message signature that enables delegation of gas payments. -In addition to retaining the previous functionality (v4), the new contract allows you to send up to 255 messages at a time, as well as to make full-fledged gasless transactions (e.g., payment of network fees when transferring USDt in USDt itself) and other features. We believe it will enhance the usability and capabilities for TON users. :::tip Wallet V5 wallets allow transactions to be initiated by the user but paid for by another contract. Consequently, there will be services (such as [Tonkeeper's Battery](https://blog.ton.org/tonkeeper-releases-huge-update#tonkeeper-battery)) that provide this functionality: they pay the transaction fees in TONs on behalf of the user, but charge a fee in tokens. From c30cb255c142b072b094eeb4f430f1c598d8cc1f Mon Sep 17 00:00:00 2001 From: Alexey Ostrovsky Date: Wed, 6 Nov 2024 14:59:50 +0300 Subject: [PATCH 05/10] wallet v5 raw --- .../contracts-specs/wallet-contracts.md | 73 ++++++++++++++++--- 1 file changed, 61 insertions(+), 12 deletions(-) diff --git a/docs/v3/documentation/smart-contracts/contracts-specs/wallet-contracts.md b/docs/v3/documentation/smart-contracts/contracts-specs/wallet-contracts.md index 848afd0923..906a394469 100644 --- a/docs/v3/documentation/smart-contracts/contracts-specs/wallet-contracts.md +++ b/docs/v3/documentation/smart-contracts/contracts-specs/wallet-contracts.md @@ -59,7 +59,7 @@ Note that wallet doesn't provide any validation of internal messages you sending ::: #### Exit codes -| Exit code | Meaning | +| Exit code | Discription | |----------------|-------------------------------------------------------------------| | 0x23 | `valid_until` check failed, transaction confirmation try too late | | 0x21 | `seqno` check failed, reply protection accured | @@ -87,7 +87,7 @@ This version introduces the `subwallet_id` parameter, which allows you to create Wallet source code: * [ton/crypto/smartcont/wallet3-code.fc](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/wallet3-code.fc) -Basically, `subwallet_id` is just a number added to the contract state when it is deployed. And since the contract address in TON is a hash of its state and code, the wallet address will change with a different `subwallet_id`. This version is the most used right now. It covers most use-cases and remains clean, simple and mostly same as previous versions. All get methods remains the same. +Basically, `subwallet_id` is just a number added to the contract state when it's deployed. And since the contract address in TON is a hash of its state and code, the wallet address will change with a different `subwallet_id`. This version is the most used right now. It covers most use-cases and remains clean, simple and mostly same as previous versions. All get methods remains the same. #### Persistend memory layout - seqno: 32-bit long sequence number. @@ -104,7 +104,7 @@ Basically, `subwallet_id` is just a number added to the contract state when it i 2. Up to 4 references to cells containing messages. #### Exit codes -| Exit code | Meaning | +| Exit code | Discription | |----------------|-------------------------------------------------------------------| | 0x23 | `valid_until` check failed, transaction confirmation try too late | | 0x23 | `Ed25519 signature` check failed | @@ -172,7 +172,7 @@ If `state_init` name doesn't tell you much by itself take a look at those refere ::: #### Exit codes -| Exit code | Meaning | +| Exit code | Discription | |----------------|--------------------------------------------------------------------------| | 0x24 | `valid_until` check failed, transaction confirmation try too late | | 0x23 | `Ed25519 signature` check failed | @@ -203,7 +203,7 @@ TL-B schemes: * [ton/crypto/block/block.tlb] (https://github.com/ton-blockchain/ton/blob/5c392e0f2d946877bb79a09ed35068f7b0bd333a/crypto/block/block.tlb#L380) :::caution -In contrast to previous wallet versions specification we will relly on [TL-B](/v3/documentation/data-formats/tlb/tl-b-language) schemes, due to relative complexity of this wallet version interfaces realization, we will provide some description for each of those, nethertheless basic understanding is still required. +In contrast to previous wallet versions specification we will relly on [TL-B](/v3/documentation/data-formats/tlb/tl-b-language) schemes, due to relative complexity of this wallet version interfaces realization, we will provide some description for each of those, nethertheless basic understanding is still required. In combination with wallet source code it should be enouth. ::: #### Persistend memory layout @@ -240,22 +240,71 @@ external_signed#7369676e signed:SignedRequest = ExternalMsgBody; Before we get to actual payload of our messages - `InnerRequest`, lets see how 5 version differs from previous at authentification process. `InternalMsgBody` combinator describes two ways to get access to wallet actions through internal messages. First one is that we are already familiar with from 4 version - authentificate as previously registered extension, address of which is stored in `extensions_dict`. Second one is authentification through stored public key and signature same as for external requests. At first it might seen as unnecessary feature, but it actually allows to proceed your request through external services(smart-contracts) which are not a part of your wallet extensions infrastructure, key feature of 5 version, gas-free transactions, relays on that functionality. +Note that just recieving funds is still an option, practically any recieved internal message which doesn't pass authentification process will be considered as so. +#### Actions -:::tip -Wallet V5 wallets allow transactions to be initiated by the user but paid for by another contract. Consequently, there will be services (such as [Tonkeeper's Battery](https://blog.ton.org/tonkeeper-releases-huge-update#tonkeeper-battery)) that provide this functionality: they pay the transaction fees in TONs on behalf of the user, but charge a fee in tokens. -::: +First thing that we should notice is `InnerRequest` that we already seen in authentification process, in contrast to previuos version both external and internal messages have access to same functionality, except changing signature mode(.e. `is_signature_allowed` flag), differs by authentification process. + +``` +out_list_empty$_ = OutList 0; +out_list$_ {n:#} + prev:^(OutList n) + action:OutAction = OutList (n + 1); + +action_send_msg#0ec3c86d mode:(## 8) out_msg:^(MessageRelaxed Any) = OutAction; + +// Extended actions in V5: +action_list_basic$_ {n:#} actions:^(OutList n) = ActionList n 0; +action_list_extended$_ {m:#} {n:#} action:ExtendedAction prev:^(ActionList n m) = ActionList n (m+1); + +action_add_ext#02 addr:MsgAddressInt = ExtendedAction; +action_delete_ext#03 addr:MsgAddressInt = ExtendedAction; +action_set_signature_auth_allowed#04 allowed:(## 1) = ExtendedAction; + +actions$_ out_actions:(Maybe OutList) has_other_actions:(## 1) {m:#} {n:#} other_actions:(ActionList n m) = InnerRequest; +``` -#### UI Preparation and Beta Testing +We can consider `InnerRequest` as two lists of actions: first `OutList` is optional chain of cell references each of those containing send message request led by message `mode`, second one `ActionList` led by one-bit flag `has_other_actions`, marking presence of extended actions, starting from first cell and continuing as chain of cell references. We are already familliar with first two extended actions `action_add_ext` and `action_delete_ext` followed by internal address that we want to add/delete from extensions dictionary. Third one `action_set_signature_auth_allowed` restricts or allows authentification through public key, leaving the only way to interact with wallet through extensions, this functionality might be extreamly important in case of lost or compromised private key. -- UI: Already now, wallet teams can start UI preparations. You can use the v5-beta smart contract as a test smart contract, but keep in mind that it will can change. UI suggestion: wallets that have multi-accounts could support the new v5 smart contract as a separate account in the UI. Provide a “Transfer funds between your accounts” functionality. -- Beta: If you build v5 functionality into public versions of your products, please mark it as “beta” and do not use the v5 contract by default, but only when explicitly enabled in the settings. Please observe this rule to prevent too wide distribution of the non-final beta version of the v5 smart contract. -- Release: The final smart contract will be ready around June 20, after which wallets can enable v5 by default using the final smart contract. It will be updated here. +:::info +Note that maximum number of actions is 255, this is a consequnce of realization through [c5](/v3/documentation/tvm/tvm-overview#result-of-tvm-execution) TVM register, technically you can make a request with empty `OutAction` and `ExtendedAction`, but in that way it will be similar to just recieving funds. +::: + +#### Exit codes +| Exit code | Discription | +|----------------|------------------------------------------------------------------------------| +| 0x84 | authentification try through signature while its disabled | +| 0x85 | `seqno` check failed, reply protection accured | +| 0x86 | `walled-id` not correspond to the stored one | +| 0x87 | `Ed25519 signature` check failed | +| 0x88 | `valid-untile` check failed | +| 0x89 | enforce that send_mode has +2 bit (ignore errors) set for external message. | +| 0x8A | `external-signed` prefix doesnt correspond to recieved one | +| 0x8B | add extension operation wasnt sucessfull | +| 0x8C | remove extension operation wasnt sucessfull | +| 0x8D | unsopported extended message prefix | +| 0x8E | try to disable auth by signature while extension dictionary is empty | +| 0x8F | setting signature try to already setted state | +| 0x90 | try to remove last extension when signature is disabled | +| 0x91 | extension wrong workchain | +| 0x92 | try to change signature mode through external message | +| 0x93 | Invalid c5, `action_send_msg` verification failed | +| 0x0 | Standard successful execution exit code. | + +:::danger +Note that `0x8E`, `0x90`, `0x92` wallet exit codes tries to prevent you from lost access to wallet functionality, nethertheless you still should remember that wallet doesnt check that stored extension addresses actually exzist in TON, also you still can deploy wallet with initial data consist of empty extensions dictionary and restricted signature mode, in that case you still we be able to get access through public key until you add your first extension, so be carefull with that moments. +::: #### Preparing for Gasless Transactions The v5 wallet smart contract allows the processing of internal messages signed by the owner. This also allows you to make gasless transactions, e.g., payment of network fees when transferring USDt in USDt itself. +:::tip +Wallet V5 wallets allow transactions to be initiated by the user but paid for by another contract. Consequently, there will be services (such as [Tonkeeper's Battery](https://blog.ton.org/tonkeeper-releases-huge-update#tonkeeper-battery)) that provide this functionality: they pay the transaction fees in TONs on behalf of the user, but charge a fee in tokens. +::: + + #### Flow 1. When sending USDt, the user signs one message containing two outgoing USDt transfers: From 403fd9651793aad1724d6d7bc3dc56cc4dd254b4 Mon Sep 17 00:00:00 2001 From: Alexey Ostrovsky Date: Wed, 6 Nov 2024 16:28:58 +0300 Subject: [PATCH 06/10] finishing v5 and minor fixes --- .../contracts-specs/wallet-contracts.md | 45 +++++++++++------- static/img/gasless.png | Bin 0 -> 58191 bytes 2 files changed, 28 insertions(+), 17 deletions(-) create mode 100644 static/img/gasless.png diff --git a/docs/v3/documentation/smart-contracts/contracts-specs/wallet-contracts.md b/docs/v3/documentation/smart-contracts/contracts-specs/wallet-contracts.md index 906a394469..21b09cbbe4 100644 --- a/docs/v3/documentation/smart-contracts/contracts-specs/wallet-contracts.md +++ b/docs/v3/documentation/smart-contracts/contracts-specs/wallet-contracts.md @@ -30,13 +30,13 @@ You can consider each wallet version as smart-contract implementation, providing This is the simplest one. It only allows you to send four transactions at the time and it doesn't check anything besides your signature and seqno. Wallet source code: - * [ton/crypto/smartcont/wallet-code.fc](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/wallet-code.fc) + * [ton/crypto/smartcont/wallet-code.fc](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/new-wallet.fif) This version isn't even used in regular apps because it has some major issues: - No easy way to retrieve the seqno and public key from the contract - No `valid_until` check, so you can't be sure that the transaction won't be confirmed too late. -The first issue is fixed in `V1R2` and secodn in `V1R3`. That `R` stands for `revision`. Usually revisions are just small updates which only add get-methods, you cand find all of those in changes history of wallet-code.fc. Hereinafter we will consider only the latest revisions. +The first issues was fixed in `V1R2` and `V1R3`. That `R` stands for `revision`. Usually revisions are just small updates which only add get-methods, you cand find all of those in changes history of new-wallet.fif. Hereinafter we will consider only the latest revisions. Nevertheless, because each subsequent version inherits the functionality of the previous one, we should still stick to it, this will help us with later versions. @@ -44,15 +44,14 @@ Nevertheless, because each subsequent version inherits the functionality of the - seqno: 32-bit long sequence number. - public-key: 256-bit long public key. -#### External message layout +#### External message body layout 1. Data: - signature: 512-bit long ed25519 signature. - msg-seqno: 32-bit long sequence number. - - valid-until: 32-bit long Unix-time integer. - (0-4)mode: up to four 8-bit long integer's defining sending mode for each message. 2. Up to 4 references to cells containing messages. -As you can see main functionality of the wallet is to provide safe way for communicating with TON blockchain from the outside world. `secno` mechanism is protecting from reply attacks, `Ed25519 signature` provides authorized access to wallet functionality and `valid-until` provide time-point limit after those message shoudn't be accepted. We will not dwell in detail on each of these mechanisms, because they are described in detail in the [external message](/v3/documentation/smart-contracts/message-management/external-messages) documentation page and they are quite common among smart-contracts recieving external messages. Payload data is up to 4 references to cells and corresponding number of modes that will be directly transfered to [send_raw_message(cell msg, int mode)](/v3/documentation/smart-contracts/func/docs/stdlib#send_raw_message) method. +As you can see main functionality of the wallet is to provide safe way for communicating with TON blockchain from the outside world. `secno` mechanism is protecting from reply attacks, `Ed25519 signature` provides authorized access to wallet functionality. We will not dwell in detail on each of these mechanisms, because they are described in detail in the [external message](/v3/documentation/smart-contracts/message-management/external-messages) documentation page and they are quite common among smart-contracts recieving external messages. Payload data is up to 4 references to cells and corresponding number of modes that will be directly transfered to [send_raw_message(cell msg, int mode)](/v3/documentation/smart-contracts/func/docs/stdlib#send_raw_message) method. :::caution Note that wallet doesn't provide any validation of internal messages you sending through it, so this is programmers(i.e. external client) responsibility to serialize data corresponding to [internal message layout](http://localhost:3000/v3/documentation/smart-contracts/message-management/sending-messages#message-layout). @@ -61,7 +60,6 @@ Note that wallet doesn't provide any validation of internal messages you sending #### Exit codes | Exit code | Discription | |----------------|-------------------------------------------------------------------| -| 0x23 | `valid_until` check failed, transaction confirmation try too late | | 0x21 | `seqno` check failed, reply protection accured | | 0x22 | `Ed25519 signature` check failed | | 0x0 | Standard successful execution exit code. | @@ -76,9 +74,21 @@ Note that [TVM](/v3/documentation/tvm/tvm-overview) has [standart exit codes](/v ### Wallet V2 -Doens't see any difference for now compare to previous, here is wallet source code: +Wallet source code: + + * [ton/crypto/smartcont/wallet-code.fc](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/wallet-code.fc) - * [ton/crypto/smartcont/new-wallet-v2.fif](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/new-wallet-v2.fif) +This version introduces the `valid_until` parameter which is used to set a time limit for a transaction in case you don't want it to be confirmed too late. This version also doesn't have the get-method for public key, which is added in `V2R2`. + +All differences compare to previous version is a consequence of adding `valid_until` functionality, all get methods remains the same, new one exit code was added: `0x23` marking failing of `valid_until` check and new UNIX-time field in external message body layout setting time limit for transaction. + +#### External message body layout +1. Data: + - signature: 512-bit long ed25519 signature. + - msg-seqno: 32-bit long sequence number. + - valid-until: 32-bit long Unix-time integer. + - (0-4)mode: up to four 8-bit long integer's defining sending mode for each message. +2. Up to 4 references to cells containing messages. ### Wallet V3 @@ -114,7 +124,7 @@ Basically, `subwallet_id` is just a number added to the contract state when it's ### Wallet V4 -It is the most modern wallet version at the moment. It still has all the functionality of the previous versions, but also introduces something very powerful — `plugins`. +This version still has all the functionality of the previous versions, but also introduces something very powerful — `plugins`. Wallet source code: * [ton-blockchain/wallet-contract](https://github.com/ton-blockchain/wallet-contract) @@ -165,7 +175,7 @@ All previous versions of wallets has pretty straightforward realization of recie As you can see fourth version still provide standart functionality though `0x0` op-code similar to previous versions. `0x2` and `0x3` operations provide manipulations for plugins dictionary, note that in case of `0x2` you need to deploy plugin with that address by yourself. `0x1` op-code in contrast also provide deployment process with `state_init` field. :::tip -If `state_init` name doesn't tell you much by itself take a look at those references: +If `state_init` doesn't tell you much by its name take a look at those references: * [addresses-in-ton-blockchain](/v3/documentation/smart-contracts/addresses#workchain-id-and-account-id) * [send-a-deploy-message](/v3/documentation/smart-contracts/func/cookbook#how-to-send-a-deploy-message-with-stateinit-only-with-stateinit-and-body) * [internal-message-layout](/v3/documentation/smart-contracts/message-management/sending-messages#message-layout) @@ -191,16 +201,15 @@ If `state_init` name doesn't tell you much by itself take a look at those refere ### Wallet V5 -This is an extensible wallet specification developed by the Tonkeeper team, aimed at replacing V4 and allowing arbitrary extensions. +It is the most modern wallet version at the moment developed by the Tonkeeper team, aimed at replacing V4 and allowing arbitrary extensions. The V5 wallet standard offers many benefits that improve the experience for both users and merchants. V5 supports gas-free transactions, account delegation and recovery, subscription payments using tokens and Toncoin, and low-cost multi-transfers. In addition to retaining the previous functionality (v4), the new contract allows you to send up to 255 messages at a time. Wallet source code: * [ton-blockchain/wallet-contract-v5](https://github.com/ton-blockchain/wallet-contract-v5) -TL-B schemes: +TL-B scheme: * [ton-blockchain/wallet-contract-v5/types.tlb] (https://github.com/ton-blockchain/wallet-contract-v5/blob/main/types.tlb) - * [ton/crypto/block/block.tlb] (https://github.com/ton-blockchain/ton/blob/5c392e0f2d946877bb79a09ed35068f7b0bd333a/crypto/block/block.tlb#L380) :::caution In contrast to previous wallet versions specification we will relly on [TL-B](/v3/documentation/data-formats/tlb/tl-b-language) schemes, due to relative complexity of this wallet version interfaces realization, we will provide some description for each of those, nethertheless basic understanding is still required. In combination with wallet source code it should be enouth. @@ -293,18 +302,19 @@ Note that maximum number of actions is 255, this is a consequnce of realization | 0x0 | Standard successful execution exit code. | :::danger -Note that `0x8E`, `0x90`, `0x92` wallet exit codes tries to prevent you from lost access to wallet functionality, nethertheless you still should remember that wallet doesnt check that stored extension addresses actually exzist in TON, also you still can deploy wallet with initial data consist of empty extensions dictionary and restricted signature mode, in that case you still we be able to get access through public key until you add your first extension, so be carefull with that moments. +Note that `0x8E`, `0x90`, `0x92` wallet exit codes tries to prevent you from lost access to wallet functionality, nethertheless you still should remember that wallet doesn't check that stored extension addresses actually exzist in TON, also you still can deploy wallet with initial data consist of empty extensions dictionary and restricted signature mode, in that case you still we be able to get access through public key until you add your first extension, so be carefull with that moments. ::: #### Preparing for Gasless Transactions -The v5 wallet smart contract allows the processing of internal messages signed by the owner. This also allows you to make gasless transactions, e.g., payment of network fees when transferring USDt in USDt itself. +As was sad before v5 wallet smart contract allows the processing of internal messages signed by the owner. This also allows you to make gasless transactions, e.g., payment of network fees when transferring USDt in USDt itself. Common scheme looks like that: + +![image](/img/gasless.png) :::tip Wallet V5 wallets allow transactions to be initiated by the user but paid for by another contract. Consequently, there will be services (such as [Tonkeeper's Battery](https://blog.ton.org/tonkeeper-releases-huge-update#tonkeeper-battery)) that provide this functionality: they pay the transaction fees in TONs on behalf of the user, but charge a fee in tokens. ::: - #### Flow 1. When sending USDt, the user signs one message containing two outgoing USDt transfers: @@ -417,4 +427,5 @@ As you see, there are many different versions of wallets in TON. But in most cas - [More technical description of versions](https://github.com/toncenter/tonweb/blob/master/src/contract/wallet/WalletSources.md) - [Wallet V4 sources and detailed description](https://github.com/ton-blockchain/wallet-contract) - [Lockup wallet sources and detailed description](https://github.com/ton-blockchain/lockup-wallet-contract) - - [Restricted wallet sources](https://github.com/EmelyanenkoK/nomination-contract/tree/master/restricted-wallet) \ No newline at end of file + - [Restricted wallet sources](https://github.com/EmelyanenkoK/nomination-contract/tree/master/restricted-wallet) + - [Gasless transactions on TON](https://medium.com/@buidlingmachine/gasless-transactions-on-ton-75469259eff2) \ No newline at end of file diff --git a/static/img/gasless.png b/static/img/gasless.png new file mode 100644 index 0000000000000000000000000000000000000000..97c9a60c5302ae08c892479252722320d4f39469 GIT binary patch literal 58191 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
*Fs^tsJhB8|M5joLpxw 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 ZzmGog?!EbYs&Ib{1sN6TGAXlH{|lhHbyWZW literal 0 HcmV?d00001 From 8ab129e36108791393feac54e5b1bbf77785f1ff Mon Sep 17 00:00:00 2001 From: Alexey Ostrovsky Date: Wed, 6 Nov 2024 17:28:16 +0300 Subject: [PATCH 07/10] grammar and syntax error fixes --- cspell.json | 2 + .../contracts-specs/wallet-contracts.md | 214 +++++++++--------- .../dapps/asset-processing/jettons.md | 2 +- 3 files changed, 113 insertions(+), 105 deletions(-) diff --git a/cspell.json b/cspell.json index be1ac66069..24b7875451 100644 --- a/cspell.json +++ b/cspell.json @@ -68,6 +68,7 @@ "Jettons", "Kademlia", "Keccak", + "Lamport", "Masterchain", "Mbit", "Merkle", @@ -279,6 +280,7 @@ "visio", "Visio", "votings", + "VARUINT16", "workchain", "workchains", "xguard", diff --git a/docs/v3/documentation/smart-contracts/contracts-specs/wallet-contracts.md b/docs/v3/documentation/smart-contracts/contracts-specs/wallet-contracts.md index 21b09cbbe4..f932f81544 100644 --- a/docs/v3/documentation/smart-contracts/contracts-specs/wallet-contracts.md +++ b/docs/v3/documentation/smart-contracts/contracts-specs/wallet-contracts.md @@ -5,20 +5,20 @@ You may have heard about different versions of wallets on the TON Blockchain. Bu In this article, we’ll explore the various versions and modifications of TON wallets. :::info -Before we start, there is some amount of therminology and concepts, that you should be familiar with to fully understand the article, such as: +Before we start, there are some terms and concepts that you should be familiar with to fully understand the article, such as - - Message managment, because this is main functionality of the wallets. - - Func language, because we will heavely relly on implementations made by it. + - Message management, because this is the main functionality of the wallets. + - FunC language, because we will heavily rely on implementations made using it. ::: -## Basic concept +## Common concept -To break the tension, at first we should understand that wallets is not some specific entity in TON ecosystem, it is still just a smart-contract consist of code and data, and, in that sence, is equal to any other actor(i.e. smart-contract) in TON. +To break the tension, we should first understand that wallets are not a specific entity in the TON ecosystem. They are still just smart contracts consisting of code and data, and, in that sense, are equal to any other actor (i.e., smart contract) in TON. -As your own custom smart-contract, or any other one, it can recieve external and internal messages, send internal messages and logs, provide get methods. -So the question is how they doing that and what functionality they providing, which is differs between versions. +Like your own custom smart contract, or any other one, wallets can receive external and internal messages, send internal messages and logs, and provide "get" methods. +So the question is: what functionality do they provide and how it differs between versions? -You can consider each wallet version as smart-contract implementation, providing standart external interface, allowing different external clients to interact with the wallets in the same way. You can find those implementation in FunC and Fift languages in main TON monorepo: +You can consider each wallet version as a smart-contract implementation providing a standard external interface, allowing different external clients to interact with the wallets in the same way. You can find these implementations in FunC and Fift languages in the main TON monorepo: * [ton/crypto/smartcont/](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/) @@ -27,20 +27,20 @@ You can consider each wallet version as smart-contract implementation, providing ### Wallet V1 -This is the simplest one. It only allows you to send four transactions at the time and it doesn't check anything besides your signature and seqno. +This is the simplest one. It only allows you to send four transactions at a time and doesn't check anything besides your signature and seqno. Wallet source code: * [ton/crypto/smartcont/wallet-code.fc](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/new-wallet.fif) -This version isn't even used in regular apps because it has some major issues: - - No easy way to retrieve the seqno and public key from the contract +This version isn’t even used in regular apps because it has some major issues: + - No easy way to retrieve the seqno and public key from the contract. - No `valid_until` check, so you can't be sure that the transaction won't be confirmed too late. -The first issues was fixed in `V1R2` and `V1R3`. That `R` stands for `revision`. Usually revisions are just small updates which only add get-methods, you cand find all of those in changes history of new-wallet.fif. Hereinafter we will consider only the latest revisions. +The first issue was fixed in `V1R2` and `V1R3`. The `R` stands for "revision". Usually, revisions are just small updates that only add get methods; you can find all of those in the changes history of `new-wallet.fif`. Hereinafter, we will consider only the latest revisions. -Nevertheless, because each subsequent version inherits the functionality of the previous one, we should still stick to it, this will help us with later versions. +Nevertheless, because each subsequent version inherits the functionality of the previous one, we should still stick to it, as this will help us with later versions. -#### Persistend memory layout +#### Persistent memory layout - seqno: 32-bit long sequence number. - public-key: 256-bit long public key. @@ -51,26 +51,26 @@ Nevertheless, because each subsequent version inherits the functionality of the - (0-4)mode: up to four 8-bit long integer's defining sending mode for each message. 2. Up to 4 references to cells containing messages. -As you can see main functionality of the wallet is to provide safe way for communicating with TON blockchain from the outside world. `secno` mechanism is protecting from reply attacks, `Ed25519 signature` provides authorized access to wallet functionality. We will not dwell in detail on each of these mechanisms, because they are described in detail in the [external message](/v3/documentation/smart-contracts/message-management/external-messages) documentation page and they are quite common among smart-contracts recieving external messages. Payload data is up to 4 references to cells and corresponding number of modes that will be directly transfered to [send_raw_message(cell msg, int mode)](/v3/documentation/smart-contracts/func/docs/stdlib#send_raw_message) method. +As you can see, the main functionality of the wallet is to provide a safe way to communicate with the TON blockchain from the outside world. The `seqno` mechanism protects against replay attacks, and the `Ed25519 signature` provides authorized access to wallet functionality. We will not dwell in detail on each of these mechanisms, as they are described in detail in the [external message](/v3/documentation/smart-contracts/message-management/external-messages) documentation page and are quite common among smart contracts receiving external messages. The payload data consists of up to 4 references to cells and the corresponding number of modes, which will be directly transferred to the [send_raw_message(cell msg, int mode)](/v3/documentation/smart-contracts/func/docs/stdlib#send_raw_message) method. :::caution -Note that wallet doesn't provide any validation of internal messages you sending through it, so this is programmers(i.e. external client) responsibility to serialize data corresponding to [internal message layout](http://localhost:3000/v3/documentation/smart-contracts/message-management/sending-messages#message-layout). +Note that the wallet doesn't provide any validation for internal messages you send through it. It is the programmer's (i.e., the external client’s) responsibility to serialize the data according to the [internal message layout](http://localhost:3000/v3/documentation/smart-contracts/message-management/sending-messages#message-layout). ::: #### Exit codes -| Exit code | Discription | +| Exit code | Description | |----------------|-------------------------------------------------------------------| | 0x21 | `seqno` check failed, reply protection accured | | 0x22 | `Ed25519 signature` check failed | | 0x0 | Standard successful execution exit code. | :::info -Note that [TVM](/v3/documentation/tvm/tvm-overview) has [standart exit codes](/v3/documentation/tvm/tvm-exit-codes) (`0x0` - is one of them), so you can get one of them too, for example, if you run out of [gas](https://docs.ton.org/develop/smart-contracts/fees) you will get `0xD` code. +Note that [TVM](/v3/documentation/tvm/tvm-overview) has [standart exit codes](/v3/documentation/tvm/tvm-exit-codes) (`0x0` - is one of them), so you can get one of them too, if you run out of [gas](https://docs.ton.org/develop/smart-contracts/fees), for example, you will get `0xD` code. ::: #### Get methods -1. int seqno() returns current stored seqno -2. int get_public_key returns current stored public key +1. int seqno() returns current stored seqno. +2. int get_public_key returns current stored public key. ### Wallet V2 @@ -78,9 +78,9 @@ Wallet source code: * [ton/crypto/smartcont/wallet-code.fc](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/wallet-code.fc) -This version introduces the `valid_until` parameter which is used to set a time limit for a transaction in case you don't want it to be confirmed too late. This version also doesn't have the get-method for public key, which is added in `V2R2`. +This version introduces the `valid_until` parameter, which is used to set a time limit for a transaction in case you don't want it to be confirmed too late. This version also does not have the get-method for the public key, which was added in `V2R2`. -All differences compare to previous version is a consequence of adding `valid_until` functionality, all get methods remains the same, new one exit code was added: `0x23` marking failing of `valid_until` check and new UNIX-time field in external message body layout setting time limit for transaction. +All differences compared to the previous version are a consequence of adding the `valid_until` functionality. A new exit code was added: `0x23`, marking the failure of the valid_until check. Additionally, a new UNIX-time field has been added to the external message body layout, setting the time limit for the transaction. All get methods remain the same. #### External message body layout 1. Data: @@ -92,72 +92,72 @@ All differences compare to previous version is a consequence of adding `valid_un ### Wallet V3 -This version introduces the `subwallet_id` parameter, which allows you to create multiple wallets using the same public key (so you can have only one seed phrase and lots of wallets). And, as before, `V3R2` only adds the get-method for public key. +This version introduces the `subwallet_id` parameter, which allows you to create multiple wallets using the same public key (so you can have only one seed phrase and multiple wallets). As before, `V3R2` only adds the get-method for the public key. Wallet source code: * [ton/crypto/smartcont/wallet3-code.fc](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/wallet3-code.fc) -Basically, `subwallet_id` is just a number added to the contract state when it's deployed. And since the contract address in TON is a hash of its state and code, the wallet address will change with a different `subwallet_id`. This version is the most used right now. It covers most use-cases and remains clean, simple and mostly same as previous versions. All get methods remains the same. +Essentially, `subwallet_id` is just a number added to the contract state when it’s deployed. Since the contract address in TON is a hash of its state and code, the wallet address will change with a different `subwallet_id`. This version is the most widely used right now. It covers most use cases and remains clean, simple, and mostly the same as previous versions. All get methods remain the same. -#### Persistend memory layout - - seqno: 32-bit long sequence number. - - subwallet: 32-bit long subwallet-id. - - public-key: 256-bit long public key. +#### Persistent Memory Layout +- seqno: 32-bit sequence number. +- subwallet: 32-bit subwallet ID. +- public-key: 256-bit public key. -#### External message layout +#### External Message Layout 1. Data: - - signature: 512-bit long ed25519 signature. - - subwallet-id: 32-bit long subwallet-id. - - msg-seqno: 32-bit long sequence number. - - valid-until: 32-bit long Unix-time integer. - - (0-4)mode: up to four 8-bit long integer's defining sending mode for each message. + - signature: 512-bit ed25519 signature. + - subwallet-id: 32-bit subwallet ID. + - msg-seqno: 32-bit sequence number. + - valid-until: 32-bit UNIX time integer. + - (0-4)mode: Up to four 8-bit integers defining the sending mode for each message. 2. Up to 4 references to cells containing messages. -#### Exit codes -| Exit code | Discription | -|----------------|-------------------------------------------------------------------| -| 0x23 | `valid_until` check failed, transaction confirmation try too late | -| 0x23 | `Ed25519 signature` check failed | -| 0x21 | `seqno` check failed, reply protection accured | -| 0x22 | `subwallet-id` not correspond to the stored one | -| 0x0 | Standard successful execution exit code. | +#### Exit Codes +| Exit Code | Description | +|----------------|--------------------------------------------------------------------------| +| 0x23 | `valid_until` check failed; transaction confirmation attempted too late | +| 0x23 | `Ed25519 signature` check failed | +| 0x21 | `seqno` check failed; reply protection triggered | +| 0x22 | `subwallet-id` does not match the stored one | +| 0x0 | Standard successful execution exit code. | ### Wallet V4 -This version still has all the functionality of the previous versions, but also introduces something very powerful — `plugins`. +This version retains all the functionality of the previous versions but also introduces something very powerful: `plugins`. Wallet source code: * [ton-blockchain/wallet-contract](https://github.com/ton-blockchain/wallet-contract) -This feature allows developers to implement complex logic that will work in tandem with a user's wallet. For example, some DApp may require a user to pay a small amount of coins every day to use some features, so the user would need to install the plugin on their wallet by signing a transaction. This plugin would send coins to the destination address daily when requested by an external message. +This feature allows developers to implement complex logic that works in tandem with a user's wallet. For example, a DApp may require a user to pay a small amount of coins every day to use certain features. In this case, the user would need to install the plugin on their wallet by signing a transaction. The plugin would then send coins to the destination address daily when requested by an external message. #### Plugins -Plugins are basically just other smart-contracts in TON that developers are free to realize the way they wanted to. In relation to wallet they are just addresses of smart-contracts stored in [dictionary](/v3/documentation/smart-contracts/func/docs/dictionaries) in wallet persisten memory, that are allowed to request funds and remove themselves from "allowed list" through sending internal messages to wallet. +Plugins are essentially other smart contracts on TON that developers are free to implement as they wish. In relation to the wallet, they are simply addresses of smart contracts stored in a [dictionary](/v3/documentation/smart-contracts/func/docs/dictionaries) in the wallet's persistent memory. These plugins are allowed to request funds and remove themselves from the "allowed list" by sending internal messages to the wallet. -#### Persistend memory layout +#### Persistent memory layout - seqno: 32-bit long sequence number. - subwallet-id: 32-bit long subwallet-id. - public-key: 256-bit long public key. - - plugins: dictionary containing plugins(might be empty) + - plugins: dictionary containing plugins(may be empty) -#### Recieving internal messages +#### Receiving internal messages -All previous versions of wallets has pretty straightforward realization of recieving internal messages, they are just accepting incoming funds from any reciever ignoring internal message body if there is one, or, in other words, have empty recv_internal method. But as was sad before fourth version of wallet has 2 additional availible operations, lets see internal message body layout: +All previous versions of wallets had a straightforward implementation for receiving internal messages. They simply accepted incoming funds from any sender, ignoring the internal message body if present, or in other words, they had an empty recv_internal method. However, as mentioned earlier, the fourth version of the wallet introduces two additional available operations. Let's take a look at the internal message body layout: -- op-code?: 32-bit long operation code. This is optional field, any message containing less then 32 bit in message body, incorrect op-code, or sender address that wasn't registred as plugin will be considered as simple transfer similar to previous wallet versions. -- query-id: 64-bit long integer. This field doesn't have any effect on smart-contract behaivour, it is used to track chain's of messages between contracts. -1. op-code = 0x706c7567, crc32("plug") - request funds operation code +- op-code?: 32-bit long operation code. This is an optional field; any message containing less than 32 bits in the message body, an incorrect op-code, or a sender address that isn't registered as a plugin will be considered as simple transfer, similar to previous wallet versions. +- query-id: 64-bit long integer. This field has no effect on the smart contract's behavior; it is used to track chains of messages between contracts. +1. op-code = 0x706c7567, request funds operation code. - toncoins: VARUINT16 amount of requested toncoins. - - extra_currencies: dictionary containing amount of requsted extra currencies(might be empty). -2. op-code = 0x64737472, crc32("dstr") - request removing of plugin-sender from "allowed list". + - extra_currencies: Dictionary containing the amount of requested extra currencies (may be empty). +2. op-code = 0x64737472, request removal of plugin-sender from the "allowed list". -#### External message layout +#### External message body layout - signature: 512-bit long ed25519 signature. - - subwallet-id: 32-bit long subwallet-id. + - subwallet-id: 32-bit long subwallet ID. - valid-until: 32-bit long Unix-time integer. - - msg-seqno: 32-bit long sequence number. + - msg-seqno: 32-bit long sequence integer. - op-code: 32-bit long operation code. 1. op-code = 0x0, simple send. - (0-4)mode: up to four 8-bit long integer's defining sending mode for each message. @@ -165,57 +165,57 @@ All previous versions of wallets has pretty straightforward realization of recie 2. op-code = 0x1, deploy and install plugin. - workchain: 8-bit long integer. - balance: VARUINT16 toncoins amount of initial balance. - - state-init: Cell reference containing plugin initital state. + - state-init: Cell reference containing plugin initial state. - body: Cell reference containing body. 3. op-code = 0x2/0x3, install plugin/remove plugin. - wc_n_address: 8-bit long workchain_id + 256-bit long plugin address. - balance: VARUINT16 toncoins amount of initial balance. - query-id: 64-bit long integer. -As you can see fourth version still provide standart functionality though `0x0` op-code similar to previous versions. `0x2` and `0x3` operations provide manipulations for plugins dictionary, note that in case of `0x2` you need to deploy plugin with that address by yourself. `0x1` op-code in contrast also provide deployment process with `state_init` field. +As you can see, the fourth version still provides standard functionality through the `0x0` op-code, similar to previous versions. The `0x2` and `0x3` operations allow manipulation of the plugins dictionary. Note that in the case of `0x2`, you need to deploy the plugin with that address yourself. In contrast, the `0x1` op-code also handles the deployment process with the state_init field. :::tip -If `state_init` doesn't tell you much by its name take a look at those references: +If `state_init` doesn't make much sense from its name, take a look at the following references: * [addresses-in-ton-blockchain](/v3/documentation/smart-contracts/addresses#workchain-id-and-account-id) * [send-a-deploy-message](/v3/documentation/smart-contracts/func/cookbook#how-to-send-a-deploy-message-with-stateinit-only-with-stateinit-and-body) * [internal-message-layout](/v3/documentation/smart-contracts/message-management/sending-messages#message-layout) ::: -#### Exit codes -| Exit code | Discription | -|----------------|--------------------------------------------------------------------------| -| 0x24 | `valid_until` check failed, transaction confirmation try too late | -| 0x23 | `Ed25519 signature` check failed | -| 0x21 | `seqno` check failed, reply protection accured | -| 0x22 | `subwallet-id` not correspond to the stored one | -| 0x27 | plugins dictionary manipulation failed(0x1-0x3 recv_external op-codes) | -| 0x50 | Not enough funds for funds request | -| 0x0 | Standard successful execution exit code. | +#### Exit Codes +| Exit Code | Description | +|----------------|------------------------------------------------------------------------------| +| 0x24 | `valid_until` check failed, transaction confirmation attempted too late | +| 0x23 | `Ed25519 signature` check failed | +| 0x21 | `seqno` check failed, reply protection triggered | +| 0x22 | `subwallet-id` does not match the stored one | +| 0x27 | Plugins dictionary manipulation failed (0x1-0x3 recv_external op-codes) | +| 0x50 | Not enough funds for the funds request | +| 0x0 | Standard successful execution exit code. | #### Get methods 1. int seqno() returns current stored seqno. 2. int get_public_key() returns current stored public key. -3. int get_subwallet_id() returns current subwallet-id. -4. int is_plugin_installed(int wc, int addr_hash) checks if plugin with defined workchain-id and address-hash installed. +3. int get_subwallet_id() returns current subwallet ID. +4. int is_plugin_installed(int wc, int addr_hash) checks if plugin with defined workchain ID and address hash is installed. 5. tuple get_plugin_list() returns list of plugins. ### Wallet V5 -It is the most modern wallet version at the moment developed by the Tonkeeper team, aimed at replacing V4 and allowing arbitrary extensions. +It is the most modern wallet version at the moment, developed by the Tonkeeper team, aimed at replacing V4 and allowing arbitrary extensions. -The V5 wallet standard offers many benefits that improve the experience for both users and merchants. V5 supports gas-free transactions, account delegation and recovery, subscription payments using tokens and Toncoin, and low-cost multi-transfers. In addition to retaining the previous functionality (v4), the new contract allows you to send up to 255 messages at a time. +The V5 wallet standard offers many benefits that improve the experience for both users and merchants. V5 supports gas-free transactions, account delegation and recovery, subscription payments using tokens and Toncoin, and low-cost multi-transfers. In addition to retaining the previous functionality (V4), the new contract allows you to send up to 255 messages at a time. Wallet source code: * [ton-blockchain/wallet-contract-v5](https://github.com/ton-blockchain/wallet-contract-v5) TL-B scheme: - * [ton-blockchain/wallet-contract-v5/types.tlb] (https://github.com/ton-blockchain/wallet-contract-v5/blob/main/types.tlb) + * [ton-blockchain/wallet-contract-v5/types.tlb](https://github.com/ton-blockchain/wallet-contract-v5/blob/main/types.tlb) :::caution -In contrast to previous wallet versions specification we will relly on [TL-B](/v3/documentation/data-formats/tlb/tl-b-language) schemes, due to relative complexity of this wallet version interfaces realization, we will provide some description for each of those, nethertheless basic understanding is still required. In combination with wallet source code it should be enouth. +In contrast to previous wallet version specifications, we will rely on [TL-B](/v3/documentation/data-formats/tlb/tl-b-language) scheme, due to the relative complexity of this wallet version's interface implementation. We will provide some description for each of those. Nevertheless, a basic understanding is still required, in combination with the wallet source code, it should be enough. ::: -#### Persistend memory layout +#### Persistent memory layout ``` contract_state$_ @@ -225,7 +225,9 @@ contract_state$_ public_key:(## 256) extensions_dict:(HashmapE 256 int1) = ContractState; ``` -As you can see `ContractState` compare to previous versions hasn't undergone big changes. Main difference is new `is_signature_allowed` 1-bit flag, that restricts or allow access through signature and stored public key. We will describe importance of that change in later topics. + + +As you can see, the `ContractState`, compared to previous versions, hasn't undergone major changes. The main difference is the new `is_signature_allowed` 1-bit flag, which restricts or allows access through the signature and stored public key. We will describe the importance of this change in later topics. #### Authentification process @@ -247,13 +249,16 @@ internal_extension#6578746e external_signed#7369676e signed:SignedRequest = ExternalMsgBody; ``` -Before we get to actual payload of our messages - `InnerRequest`, lets see how 5 version differs from previous at authentification process. `InternalMsgBody` combinator describes two ways to get access to wallet actions through internal messages. First one is that we are already familiar with from 4 version - authentificate as previously registered extension, address of which is stored in `extensions_dict`. Second one is authentification through stored public key and signature same as for external requests. At first it might seen as unnecessary feature, but it actually allows to proceed your request through external services(smart-contracts) which are not a part of your wallet extensions infrastructure, key feature of 5 version, gas-free transactions, relays on that functionality. -Note that just recieving funds is still an option, practically any recieved internal message which doesn't pass authentification process will be considered as so. +Before we get to the actual payload of our messages — `InnerRequest` — let's first look at how version 5 differs from previous versions in the authentication process. The `InternalMsgBody` combinator describes two ways to access wallet actions through internal messages. The first method is one we are already familiar with from version 4: authentication as a previously registered extension, the address of which is stored in `extensions_dict`. The second method is authentication through the stored public key and signature, similar to external requests. + +At first, this might seem like an unnecessary feature, but it actually enables requests to be processed through external services (smart contracts) that are not part of your wallet's extension infrastructure—a key feature of V5. Gas-free transactions rely on this functionality. + +Note that simply receiving funds is still an option. Practically, any received internal message that doesn't pass the authentication process will be considered as transfer. #### Actions -First thing that we should notice is `InnerRequest` that we already seen in authentification process, in contrast to previuos version both external and internal messages have access to same functionality, except changing signature mode(.e. `is_signature_allowed` flag), differs by authentification process. +The first thing that we should notice is `InnerRequest`, which we have already seen in the authentication process. In contrast to the previous version, both external and internal messages have access to the same functionality, except for changing the signature mode (i.e., the `is_signature_allowed` flag). ``` out_list_empty$_ = OutList 0; @@ -274,35 +279,36 @@ action_set_signature_auth_allowed#04 allowed:(## 1) = ExtendedAction; actions$_ out_actions:(Maybe OutList) has_other_actions:(## 1) {m:#} {n:#} other_actions:(ActionList n m) = InnerRequest; ``` -We can consider `InnerRequest` as two lists of actions: first `OutList` is optional chain of cell references each of those containing send message request led by message `mode`, second one `ActionList` led by one-bit flag `has_other_actions`, marking presence of extended actions, starting from first cell and continuing as chain of cell references. We are already familliar with first two extended actions `action_add_ext` and `action_delete_ext` followed by internal address that we want to add/delete from extensions dictionary. Third one `action_set_signature_auth_allowed` restricts or allows authentification through public key, leaving the only way to interact with wallet through extensions, this functionality might be extreamly important in case of lost or compromised private key. +We can consider `InnerRequest` as two lists of actions: the first, `OutList`, is an optional chain of cell references, each containing a send message request led by the message mode. The second, `ActionList,` is led by a one-bit flag, `has_other_actions`, which marks the presence of extended actions, starting from the first cell and continuing as a chain of cell references. We are already familiar with the first two extended actions, `action_add_ext` and `action_delete_ext`, followed by the internal address that we want to add or delete from the extensions dictionary. The third, `action_set_signature_auth_allowed`, restricts or allows authentication through the public key, leaving the only way to interact with the wallet through extensions. This functionality might be extremely important in the case of a lost or compromised private key. :::info -Note that maximum number of actions is 255, this is a consequnce of realization through [c5](/v3/documentation/tvm/tvm-overview#result-of-tvm-execution) TVM register, technically you can make a request with empty `OutAction` and `ExtendedAction`, but in that way it will be similar to just recieving funds. +Note that the maximum number of actions is 255; this is a consequence of the realization through the [c5](/v3/documentation/tvm/tvm-overview#result-of-tvm-execution) TVM register. Technically, you can make a request with empty `OutAction` and `ExtendedAction`, but in that case, it will be similar to just receiving funds. ::: -#### Exit codes -| Exit code | Discription | -|----------------|------------------------------------------------------------------------------| -| 0x84 | authentification try through signature while its disabled | -| 0x85 | `seqno` check failed, reply protection accured | -| 0x86 | `walled-id` not correspond to the stored one | -| 0x87 | `Ed25519 signature` check failed | -| 0x88 | `valid-untile` check failed | -| 0x89 | enforce that send_mode has +2 bit (ignore errors) set for external message. | -| 0x8A | `external-signed` prefix doesnt correspond to recieved one | -| 0x8B | add extension operation wasnt sucessfull | -| 0x8C | remove extension operation wasnt sucessfull | -| 0x8D | unsopported extended message prefix | -| 0x8E | try to disable auth by signature while extension dictionary is empty | -| 0x8F | setting signature try to already setted state | -| 0x90 | try to remove last extension when signature is disabled | -| 0x91 | extension wrong workchain | -| 0x92 | try to change signature mode through external message | -| 0x93 | Invalid c5, `action_send_msg` verification failed | -| 0x0 | Standard successful execution exit code. | +#### Exit Codes + +| Exit Code | Description | +|----------------|----------------------------------------------------------------------------------| +| 0x84 | Authentication attempt through signature while it's disabled | +| 0x85 | `seqno` check failed, reply protection occurred | +| 0x86 | `wallet-id` does not correspond to the stored one | +| 0x87 | `Ed25519 signature` check failed | +| 0x88 | `valid-until` check failed | +| 0x89 | Enforce that `send_mode` has the +2 bit (ignore errors) set for external message.| +| 0x8A | `external-signed` prefix doesn't correspond to the received one | +| 0x8B | Add extension operation was not successful | +| 0x8C | Remove extension operation was not successful | +| 0x8D | Unsupported extended message prefix | +| 0x8E | Tried to disable auth by signature while the extension dictionary is empty | +| 0x8F | Attempt to set signature to an already set state | +| 0x90 | Tried to remove the last extension when signature is disabled | +| 0x91 | Extension has the wrong workchain | +| 0x92 | Tried to change signature mode through external message | +| 0x93 | Invalid `c5`, `action_send_msg` verification failed | +| 0x0 | Standard successful execution exit code. | :::danger -Note that `0x8E`, `0x90`, `0x92` wallet exit codes tries to prevent you from lost access to wallet functionality, nethertheless you still should remember that wallet doesn't check that stored extension addresses actually exzist in TON, also you still can deploy wallet with initial data consist of empty extensions dictionary and restricted signature mode, in that case you still we be able to get access through public key until you add your first extension, so be carefull with that moments. +Note that the `0x8E`, `0x90`, and `0x92` wallet exit codes are designed to prevent you from losing access to wallet functionality. Nevertheless, you should still remember that the wallet doesn't check whether the stored extension addresses actually exist in TON. You can also deploy a wallet with initial data consisting of an empty extensions dictionary and restricted signature mode. In that case, you will still be able to access the wallet through the public key until you add your first extension. So, be careful with these scenarios. ::: #### Preparing for Gasless Transactions diff --git a/docs/v3/guidelines/dapps/asset-processing/jettons.md b/docs/v3/guidelines/dapps/asset-processing/jettons.md index c599075058..b1ab32e080 100644 --- a/docs/v3/guidelines/dapps/asset-processing/jettons.md +++ b/docs/v3/guidelines/dapps/asset-processing/jettons.md @@ -71,7 +71,7 @@ For the best user experience, it is suggested to avoid waiting on additional blo Quick jump to the core description of jetton processing: - +