From 9dd1a63d84f551ec0dc0eff643df1ae35fbc9aaa Mon Sep 17 00:00:00 2001
From: kaladin <335095@niuitmo.ru>
Date: Wed, 5 Nov 2025 12:40:13 +0300
Subject: [PATCH 01/13] draft
---
payments/toncoin.mdx | 74 ++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 72 insertions(+), 2 deletions(-)
diff --git a/payments/toncoin.mdx b/payments/toncoin.mdx
index 852268608..f5b89a5b4 100644
--- a/payments/toncoin.mdx
+++ b/payments/toncoin.mdx
@@ -3,6 +3,76 @@ title: "Toncoin payments processing"
sidebarTitle: "Toncoin"
---
-import { Stub } from '/snippets/stub.jsx';
+import { Aside } from "/snippets/aside.jsx";
-
+Processing Toncoin payments requires choosing between two architectural approaches: invoice-based deposits to a single address or unique deposit addresses per user. Each approach has different security characteristics, implementation complexity, and operational requirements.
+
+## Invoice-based deposits
+
+Invoice-based processing uses a single wallet address to receive payments from multiple users. Each payment includes a unique identifier in the transaction comment field, allowing the service to attribute deposits to specific users.
+
+The implementation deploys one wallet contract (typically [Highload](/standard/wallets/highload/overview)) and generates unique invoice identifiers for each deposit. Users send Toncoin to this shared address with their invoice identifier as the comment. The service polls the wallet's transaction history, extracts comments from incoming messages, matches them against stored invoices, and credits user accounts accordingly.
+
+Transaction comments in TON use the text message format with opcode `0x00000000` (first 32 bits of incoming internal message body) followed by UTF-8 encoded text. When parsing incoming messages, check the message body's first 32 bits for this opcode before reading the comment. Some wallets may send empty comments or messages without text format, so handle these cases gracefully.
+
+
+
+
+**Advantages**:
+- Single wallet simplifies key management
+- Reduced gas costs for deployments
+- Withdrawals can batch multiple user requests into one transaction using a Highload wallet
+- The approach scales well for high transaction volumes
+
+**Disadvantages**:
+- Privacy is reduced since all users deposit to the same observable address
+- Users must correctly input the invoice identifier, and mistakes result in lost or misdirected funds
+- Comment parsing adds complexity
+- Some wallets don't support comments, limiting accessibility
+
+Reference education-only implementation: [Invoice-based Toncoin deposits](https://github.com/ton-org/docs-examples/blob/processing/guidebook/payment-processing/src/deposits.ts).
+
+## Unique deposit addresses
+
+Unique address deposits generate a separate wallet contract for each user. The user deposits to their dedicated address, and the service monitors all deployed wallets for incoming transactions. No comment parsing is required since each address maps to exactly one user.
+
+Implementation requires a wallet generation strategy. The most common approach uses a deterministic scheme based on a master seed and user identifiers. For V4 and V5 wallets, use different `subwallet_id` combinations. Alternatively, generate unique keypairs per user, though this increases key management complexity. (TODO: security!)
+
+Wallet deployment happens lazily when users first request their deposit address. Generate the address deterministically without deploying the contract. When the user sends their first deposit to the undeployed address, send the transaction in non-bounceable mode. The contract doesn't exist yet, so bounceable messages would return the funds. After the first deposit arrives, deploy the contract using funds from that deposit or from an external source.
+
+Monitor all user wallets by maintaining a list of deployed addresses and polling their transactions. For large user bases, this becomes resource-intensive. Optimization strategies include monitoring only active wallets (those with recent deposits), using batched RPC calls to check multiple wallets per request.
+
+TON's sharding mechanism splits the network across multiple chains based on address prefixes. The shard prefix comes from the first bits of the address hash. Deploying wallets in the same shard reduces cross-shard communication overhead. TODO: ton/core prefix
+
+
+
+Withdrawal processing must gather funds from multiple wallets. Either maintain a minimum balance in each wallet for gas fees or implement a fund collection system that periodically sweeps deposits to a central hot wallet. Highload wallets handle batch withdrawals efficiently, while standard V4/V5 wallets process messages sequentially using `seqno`, creating bottlenecks under high load.
+
+**Advantages**:
+- No comment parsing removes a major source of user error
+- Better privacy since each user has a unique address
+- Transaction monitoring is straightforward - any incoming transaction to a user's address is their deposit
+
+**Disadvantages**:
+- Higher operational complexity managing multiple wallets
+- Deployment costs multiply by the number of users
+- Withdrawal processing requires coordination across wallets
+- Storage fees apply to each deployed contract (currently ~0.001 TON per year per contract)
+
+## Withdrawal batching
+
+[Highload wallets](/standard/wallets/highload/overview) support parallel message processing by storing processed request identifiers instead of sequential `seqno`. This enables batching multiple withdrawals into one transaction, reducing fees and improving throughput.
+
+## Monitoring best practices
+
+Implement exponential backoff for RPC failures. Network issues or node maintenance can interrupt transaction polling. When `getTransactions` fails, wait before retrying with increasing delays to avoid overwhelming the endpoint.
+
+Store transaction state persistently. Record the last processed `lt` value and transaction hash to resume monitoring after restarts without reprocessing transactions. This prevents duplicate deposit credits.
+
+Use multiple RPC endpoints for reliability. TON has several public API providers and liteserver networks. Implement fallback logic to switch endpoints if the primary becomes unavailable. Compare results across endpoints to detect potential inconsistencies.
+
+Log all processing decisions including deposit credits, withdrawal submissions, and failed transactions. These logs are essential for debugging user reports and auditing system behavior. Include transaction hashes, logical times, amounts, and user identifiers in logs.
From fe1d096625e71efa4885ef5ae65f154b85cbda82 Mon Sep 17 00:00:00 2001
From: kaladin <335095@niuitmo.ru>
Date: Thu, 6 Nov 2025 12:53:58 +0300
Subject: [PATCH 02/13] review
---
payments/toncoin.mdx | 51 +++++++++++++++++++++++++++++++++-----------
1 file changed, 38 insertions(+), 13 deletions(-)
diff --git a/payments/toncoin.mdx b/payments/toncoin.mdx
index f5b89a5b4..3e0f5cdea 100644
--- a/payments/toncoin.mdx
+++ b/payments/toncoin.mdx
@@ -5,21 +5,34 @@ sidebarTitle: "Toncoin"
import { Aside } from "/snippets/aside.jsx";
-Processing Toncoin payments requires choosing between two architectural approaches: invoice-based deposits to a single address or unique deposit addresses per user. Each approach has different security characteristics, implementation complexity, and operational requirements.
+Processing Toncoin payments requires choosing between two architectural approaches: invoice-based deposits to a single address, common to all users or unique deposit addresses per user. Each approach has different security characteristics, implementation complexity, and operational requirements.
+
+**Invoice-based flow**
+
+```mermaid
+graph LR
+ U1[User A] -- invoice UUID --> SW[Shared Wallet]
+ U2[User B] -- invoice UUID --> SW
+ SW --> EX[Exchange Ledger]
+```
+
+**Unique deposit address flow**
+```mermaid
+graph LR
+ U1[User A] --> W1[Wallet A]
+ W1 --> EX[Exchange Ledger]
+ U2[User B] --> W2[Wallet B]
+ W2 --> EX
+```
## Invoice-based deposits
-Invoice-based processing uses a single wallet address to receive payments from multiple users. Each payment includes a unique identifier in the transaction comment field, allowing the service to attribute deposits to specific users.
+Invoice-based processing uses one wallet address to receive payments from all users. Each payment includes a unique identifier in the transaction comment field, allowing the service to attribute deposits to specific users.
-The implementation deploys one wallet contract (typically [Highload](/standard/wallets/highload/overview)) and generates unique invoice identifiers for each deposit. Users send Toncoin to this shared address with their invoice identifier as the comment. The service polls the wallet's transaction history, extracts comments from incoming messages, matches them against stored invoices, and credits user accounts accordingly.
+The implementation deploys one wallet contract (typically [Highload](/standard/wallets/highload/overview)) and generates unique invoice identifiers for each deposit. Users send Toncoin to this shared address with their invoice identifier as the comment. TODO: link. The service polls the wallet's transaction history, extracts comments from incoming messages, matches them against stored invoices, and credits user accounts accordingly.
Transaction comments in TON use the text message format with opcode `0x00000000` (first 32 bits of incoming internal message body) followed by UTF-8 encoded text. When parsing incoming messages, check the message body's first 32 bits for this opcode before reading the comment. Some wallets may send empty comments or messages without text format, so handle these cases gracefully.
-
-
-
**Advantages**:
- Single wallet simplifies key management
- Reduced gas costs for deployments
@@ -27,10 +40,11 @@ Transaction comments in TON use the text message format with opcode `0x00000000`
- The approach scales well for high transaction volumes
**Disadvantages**:
-- Privacy is reduced since all users deposit to the same observable address
+- Access leak to the singlew hot wallet could lead to all user funds loss
- Users must correctly input the invoice identifier, and mistakes result in lost or misdirected funds
- Comment parsing adds complexity
-- Some wallets don't support comments, limiting accessibility
+- Some user wallet applications don't support comments, limiting accessibility
+- Single wallet network load [won't be sharded](/foundations/shards)
Reference education-only implementation: [Invoice-based Toncoin deposits](https://github.com/ton-org/docs-examples/blob/processing/guidebook/payment-processing/src/deposits.ts).
@@ -38,11 +52,15 @@ Reference education-only implementation: [Invoice-based Toncoin deposits](https:
Unique address deposits generate a separate wallet contract for each user. The user deposits to their dedicated address, and the service monitors all deployed wallets for incoming transactions. No comment parsing is required since each address maps to exactly one user.
-Implementation requires a wallet generation strategy. The most common approach uses a deterministic scheme based on a master seed and user identifiers. For V4 and V5 wallets, use different `subwallet_id` combinations. Alternatively, generate unique keypairs per user, though this increases key management complexity. (TODO: security!)
+Implementation requires a wallet generation strategy. The most common approach uses a deterministic scheme based on a master seed and user identifiers. For V4 and V5 wallets, use different `subwallet_id` combinations. Alternatively, generate unique keypairs per user, though this increases key management complexity.
+
+
Wallet deployment happens lazily when users first request their deposit address. Generate the address deterministically without deploying the contract. When the user sends their first deposit to the undeployed address, send the transaction in non-bounceable mode. The contract doesn't exist yet, so bounceable messages would return the funds. After the first deposit arrives, deploy the contract using funds from that deposit or from an external source.
-Monitor all user wallets by maintaining a list of deployed addresses and polling their transactions. For large user bases, this becomes resource-intensive. Optimization strategies include monitoring only active wallets (those with recent deposits), using batched RPC calls to check multiple wallets per request.
+Monitor all user wallets by maintaining a list of deployed addresses and polling their transactions. For large user bases, this becomes resource-intensive. Optimization strategies include monitoring only active wallets (those with recent deposits), using batched RPC calls to check multiple wallets per request. TODO: batch
TON's sharding mechanism splits the network across multiple chains based on address prefixes. The shard prefix comes from the first bits of the address hash. Deploying wallets in the same shard reduces cross-shard communication overhead. TODO: ton/core prefix
@@ -54,7 +72,7 @@ Withdrawal processing must gather funds from multiple wallets. Either maintain a
**Advantages**:
- No comment parsing removes a major source of user error
-- Better privacy since each user has a unique address
+- Better security since each user has a unique keypair
- Transaction monitoring is straightforward - any incoming transaction to a user's address is their deposit
**Disadvantages**:
@@ -67,6 +85,13 @@ Withdrawal processing must gather funds from multiple wallets. Either maintain a
[Highload wallets](/standard/wallets/highload/overview) support parallel message processing by storing processed request identifiers instead of sequential `seqno`. This enables batching multiple withdrawals into one transaction, reducing fees and improving throughput.
+## Common abuse patterns
+
+- Reusing a previously settled invoice identifier to trigger duplicate credits when the backend does not invalidate the invoice after first use.
+- Changing the Toncoin amount but leaving the original invoice identifier to obtain services at a lower price if expected amounts are not enforced.
+- Crafting comments that mimic another users invoice identifier in order to hijack their pending credit.
+- Submitting large numbers of dust payments to inflate processing costs or exhaust rate limits on transaction polling.
+
## Monitoring best practices
Implement exponential backoff for RPC failures. Network issues or node maintenance can interrupt transaction polling. When `getTransactions` fails, wait before retrying with increasing delays to avoid overwhelming the endpoint.
From b5596bfebc465e09d88eeba4aeb5483373f333f1 Mon Sep 17 00:00:00 2001
From: kaladin <335095@niuitmo.ru>
Date: Thu, 6 Nov 2025 13:09:11 +0300
Subject: [PATCH 03/13] todos
---
payments/toncoin.mdx | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/payments/toncoin.mdx b/payments/toncoin.mdx
index 3e0f5cdea..c66a58967 100644
--- a/payments/toncoin.mdx
+++ b/payments/toncoin.mdx
@@ -29,9 +29,9 @@ graph LR
Invoice-based processing uses one wallet address to receive payments from all users. Each payment includes a unique identifier in the transaction comment field, allowing the service to attribute deposits to specific users.
-The implementation deploys one wallet contract (typically [Highload](/standard/wallets/highload/overview)) and generates unique invoice identifiers for each deposit. Users send Toncoin to this shared address with their invoice identifier as the comment. TODO: link. The service polls the wallet's transaction history, extracts comments from incoming messages, matches them against stored invoices, and credits user accounts accordingly.
+The implementation deploys one wallet contract (typically [Highload](/standard/wallets/highload/overview)) and generates unique invoice identifiers for each deposit. Users send Toncoin to this shared address with their invoice identifier as the comment. The service polls the wallet's transaction history, extracts comments from incoming messages, matches them against stored invoices, and credits user accounts accordingly.
-Transaction comments in TON use the text message format with opcode `0x00000000` (first 32 bits of incoming internal message body) followed by UTF-8 encoded text. When parsing incoming messages, check the message body's first 32 bits for this opcode before reading the comment. Some wallets may send empty comments or messages without text format, so handle these cases gracefully.
+Transaction comments in TON use the text message format, read more about them [here](/standard/wallets/how-it-works#transfer-comments).
**Advantages**:
- Single wallet simplifies key management
@@ -60,9 +60,9 @@ Implementation requires a wallet generation strategy. The most common approach u
Wallet deployment happens lazily when users first request their deposit address. Generate the address deterministically without deploying the contract. When the user sends their first deposit to the undeployed address, send the transaction in non-bounceable mode. The contract doesn't exist yet, so bounceable messages would return the funds. After the first deposit arrives, deploy the contract using funds from that deposit or from an external source.
-Monitor all user wallets by maintaining a list of deployed addresses and polling their transactions. For large user bases, this becomes resource-intensive. Optimization strategies include monitoring only active wallets (those with recent deposits), using batched RPC calls to check multiple wallets per request. TODO: batch
+Monitor all user wallets by maintaining a list of deployed addresses and polling their transactions. For large user bases, this becomes resource-intensive. Optimization strategies include monitoring only active wallets (those with recent deposits), using batched RPC calls to check multiple wallets per request.
-TON's sharding mechanism splits the network across multiple chains based on address prefixes. The shard prefix comes from the first bits of the address hash. Deploying wallets in the same shard reduces cross-shard communication overhead. TODO: ton/core prefix
+TON's sharding mechanism splits the network across multiple chains based on address prefixes. The shard prefix comes from the first bits of the address hash. Deploying wallets in the same shard reduces cross-shard communication overhead.