Original author: Johan

background

TON (The Open Network) is a decentralized blockchain platform originally designed and developed by the Telegram team. TON's goal is to provide a high-performance and scalable blockchain platform to support large-scale decentralized applications (DApps) and smart contracts.

TON is so special. It is easy to use. It is deeply integrated with Telegram, making it easy for ordinary people to use tokens. It is also complex. It has a completely different architecture from other blockchains and uses the non-mainstream FunC smart contract language. Today we will discuss the characteristics of TON and the security of user assets from the perspectives of accounts, tokens, and transactions.

Features of TON

Account Generation

The way TON account address is generated is different from most blockchains. It is a smart contract address. First, a private key is generated. TON mainly uses Ed 25519 algorithm to generate public key. The generation process is as follows:

There are two forms of public keys. One is the original public key calculated from the private key, which looks like:

E39ECDA0A7B0C60A7107EC43967829DBE8BC356A49B9DFC6186B3EAC74B5477D

The other is a "beautified" public key, which carries some information and check bits of the public key, such as: Pubjns2gp7DGCnEH7EOWeCnb6Lw1akm538YYaz6sdLVHfRB2

It is naive to think that you can get the account address just by getting the public key, just like Ethereum. Just having the user's public key is not enough to calculate the user's account address. We just said that the user's account address is a smart contract address, but we don't even have an account, how can we deploy a smart contract? The correct order is to calculate the address first, receive a little initial amount of tokens, and then deploy the contract. The calculation process of the account address is shown in the figure below:

The user's address also has multiple forms. The first is the original form, which looks like:

0:b4c1b2ede12aa76f4a44353944258bcc8f99e9c7c474711a152c78b43218e296

And user-friendly forms like:

Mainnet:

Bounceable:

EQC0wbLt4Sqnb0pENTlEJYvMj5npx8R0cRoVLHi0MhjilkPX

Non-bounceable:

UQC0wbLt4Sqnb0pENTlEJYvMj5npx8R0cRoVLHi0Mhjilh4S

Testnet:

Bounceable:

kQC0wbLt4Sqnb0pENTlEJYvMj5npx8R0cRoVLHi0Mhjilvhd

Non-bounceable:

0QC0wbLt4Sqnb0pENTlEJYvMj5npx8R0cRoVLHi0MhjilqWY

A careful observation of these addresses shows that they differ only in the first and last characters. The `account_id` in the middle is the same, but we still cannot see the relationship between the public key and the account address. In fact, the mystery lies in the `initial data` at the beginning, which contains a user's public key, through which the user controls the ownership of the wallet contract. `workchainId` is easy to understand. TON is not just a single chain. It is composed of a lot of shards. Each shard is part of the entire network and handles a specific set of accounts and transactions. In order to locate and manage smart contracts, it is necessary to clearly indicate which shard they are located in. What is the difference between `Bounceable` and `Non-bounceable`? This is related to the working mechanism of smart contracts. Let's continue to look down.

Wallet Contract

The following is a source code of a user wallet contract. You can see that it reads 4 parameters (stored_seqno, stored_subwallet, public_key, plugins) when receiving a message from the user:

wallet-v4-code.fc

() recv_external(slice in_msg) impure {

var signature = in_msg~load_bits( 512);

var cs = in_msg;

var (subwallet_id, valid_until, msg_seqno) = (cs~load_uint( 32), cs~load_uint( 32), cs~load_uint( 32));

throw_if( 36, valid_until <= now());

var ds = get_data().begin_parse();

var (stored_seqno, stored_subwallet, public_key, plugins) = (ds~load_uint( 32), ds~load_uint( 32), ds~load_uint( 256), ds~load_dict()); ;;#TheInitial Data

ds.end_parse();

throw_unless( 33, msg_seqno == stored_seqno);

throw_unless( 34, subwallet_id == stored_subwallet);

throw_unless( 35, check_signature(slice_hash(in_msg), signature, public_key));

//...

}

That's right. When deploying this user's wallet contract, some initial parameters need to be passed in, including a 256-bit public_key information, which ensures that each user has an independent contract address when using the same contract code. All transactions initiated by the user need to sign `in_msg`, and then verify the signature (check_signature) through their own wallet contract, and then the contract will call all operations on the chain. From this we can also infer that a user's public key can actually correspond to countless wallet addresses. You only need to deploy wallets with different source codes or different initialization data to get completely different contract addresses.

Jetton Token

Token is the representation of assets on the chain, so it is a basic element we need to understand. Jetton is the standard form of TON token. Jetton consists of two contracts, Jetton-minter and Jetton-wallet:

When a token is issued, a Jetton-minter contract is created. The contract initialization records information such as the total amount of tokens, administrators, wallet codes, etc.

When tokens are distributed to users, the Minter contract will deploy a wallet contract for the user and record the user's balance, ownership, token Minter contract address, user wallet code and other information when the contract is initialized. Each user will deploy a contract independently. Note that the contract created here is a wallet contract for managing specific Jetton tokens, which is different from the user's account wallet contract. The owner_address here records the user's account wallet address.

When user Alice transfers money to user Bob, the calling relationship is as follows:

Alice signs the off-chain APP and issues operation instructions by calling her wallet contract. These instructions will further call her token wallet to transfer the token. When Bob's token wallet receives the token, it will notify Bob's wallet contract (that is, the Owner address of Bob Jetton-wallet). If there is remaining Gas during the transaction, it will also be returned to the response address, usually Alice's account contract.

This is a Jetton token transfer as parsed by the Tonviewer browser:

An ERC 20 transfer requires at least one contract call, while a Jetton token transfer requires at least four contracts. This is done to allow transfers to be performed concurrently on the chain, improving transaction efficiency.

trade

When certain events occur to an account in TON, it triggers a transaction. The most common event is "receiving a message". The transaction includes the following:

  • The incoming message that initially triggered the contract (there are special triggering methods)

  • Contract actions caused by incoming messages, such as updating the contract's storage (optional)

  • Outgoing messages to other participants (optional)

There are several features to note when trading:

1. Asynchronous: TON transactions are not completed in one call. It may need to pass messages to multiple different smart contracts to execute a series of calls. Due to different routings in the shard chain, TON cannot guarantee the order of message passing between multiple smart contracts.

2. Handling Fees: The asynchronous nature also brings a problem, that is, the consumed handling fees are difficult to estimate. Therefore, when initiating a transaction, the wallet usually sends more tokens as handling fees. If the called contract has a good handling fee processing mechanism, the remaining handling fees will eventually be returned to the user's wallet. Users may observe that the wallet tokens suddenly become less, and then become more after a few minutes. This is the reason.

3. Bounce: Bounce is an error handling mechanism of the contract. When the called contract does not exist or throws an error, if the transaction is set to be bounceable, a bounced message will be bounced back to the contract that initiated the call. For example: if a user initiates a transfer and the call process goes wrong, a bounce message is required so that the user's wallet contract can restore its balance. Almost all internal messages sent between smart contracts should be bounceable, that is, their "bounce" bit should be set.

Asset Security

TON has many features that pose security issues, so users also need to be aware of some common pitfalls.

Fee Withholding Attack

As mentioned above, wallets often need to send more fees to prevent transaction execution failures, which gives attackers an opportunity to do evil. If you are a TON wallet user, you may have encountered such a situation. You always receive various NFTs or tokens in your wallet. You thought they were just some junk token airdrops, but when you checked the transaction information, you found that they could be sold for a lot of money? However, when you initiate a transaction, you find that the required fee is extremely high (1 TON). At this time, you need to pay attention, as this may be a fee scam.

The attacker used a carefully constructed token contract to make the wallet's estimated transfer fee extremely high, but in actual execution, only the fee was intercepted and no transfer message was sent.

First and last number fishing

Phishing with the first and last digits is not unique to TON, it exists in all major public chains. The attacker will generate a high-imitation account with the same first and last digits for each user address on the entire network. When the user sends a transfer, the attacker also sends a small transfer with the high-imitation account, with the purpose of leaving a record in the user's payment record. When the recipient wants to transfer a token back, he may copy the address from the historical record, and it is likely to be copied to the attacker's address, resulting in the transfer to the wrong address. The attacker can accurately grasp the user's behavior.

comment fishing

TON can add a comment when transferring money to note the transaction information. This function is frequently used when recharging on exchanges. Exchanges usually require users to note their user ID when recharging. However, this function is often used maliciously. Attackers write fraudulent information in the comments to defraud users' assets. As shown in the figure:

Users need to pay special attention to the Anonymous Telegram Number NFT. If a user opens a TG number with an Anonymous Telegram Number but does not enable Two-Step Verification, once this NFT is phished away, hackers can directly log in to the target TG number and carry out subsequent asset theft and fraud.

Smart Contract Vulnerabilities

Security vulnerabilities in smart contracts can cause users to lose funds placed in smart contracts. Users need to choose projects that have been well audited. TON's smart contracts are mainly programmed using the FunC language, and some use the more advanced Tact or the more basic Fift, which are highly original languages. New programming languages ​​bring new security risks, especially for developers. They need to have good habits of secure programming, master the best security practices, and undergo strict security audits before deploying to the production environment. Due to space limitations, this article does not discuss contract security.

Fake recharge attack

Wallet or exchange users need to be aware of fake deposit attacks, which generally fall into two categories:

  • Fake coins: The attacker issues a token with the same metadata as the target token. If the automated account entry program does not check whether this is the correct minter contract, it will lead to incorrect account entry.

  • Bounce, TON's transfer process requires a call relationship between the wallet contracts of two users. If the recipient's wallet contract does not exist and the transaction is set to Bounceable, the message will be bounced and the original funds will be returned to the sender after deducting the handling fee. Friends who are interested in the details can check out our previously disclosed fake recharge article.

Summarize

This article introduces some basic technical principles of TON from the perspectives of TON's public and private key creation, wallet contracts, token forms, transaction characteristics, etc. It also discusses possible security issues that may exist in the process of using TON, hoping to bring inspiration to everyone's learning.

Reference Links:

https://docs.ton.org/

https://github.com/ton-blockchain/wallet-contract