TON security record

BNB Chain, Ethereumton.orgXGitHub

As of 10 Nov 2026, TON has 6 audit reports by 2 security firms on Trustblock; the latest is by Trail of Bits, dated 25 Mar 2024. Those reports list no open critical findings.

Critical findings
No open critical findings
Across 6 reports.
Open the latest report
Your label, live
Get the label for your site

Record last updated . It holds audits and findings, contracts and incidents up to Nov 2026. Trustblock does not review code.

Audits5· Formal verifications 1

Newest first

1 other security report listed, not counted

ReportSecurity firmDateScopeCritical findingsSource
TON Foundation Multisignature WalletSecurity firm: Trail of BitsDate: Scope: Not recorded; see the reportNone openGitHub ↗
TON-EVM BridgeSecurity firm: CertiKDate: Scope: Files listedNone openskynet.certik.com ↗
TON StablecoinSecurity firm: CertiKDate: Scope: Not recorded; see the reportNone openskynet.certik.com ↗
Ton Bridge Web Application

Penetration test of off-chain systemsNot counted as an audit report

Security firm: CertiKDate: Scope: Not recorded; see the reportNone openskynet.certik.com ↗
TON Masterchain Contracts Formal VerificationFormal verificationSecurity firm: CertiKDate: Scope: Not recorded; see the reportNone openskynet.certik.com ↗
TON VestingSecurity firm: CertiKDate: Scope: Not recorded; see the reportNone openskynet.certik.com ↗
The Open Network - Audit 1 (Phase 2)Security firm: CertiKDate: Scope: Not recorded; see the reportNone openskynet.certik.com ↗

Findings77

Statuses are the security firm’s own, from each report.

SeverityOpenAcknowledgedFixed
Critical000
High312
Medium2011
Low17037
HighMalicious orders can create and execute new ordersTON Foundation Multisignature Wallet · Trail of Bits · 25 Mar 2024Open

The report gives no description here.

Open the report
HighAll the money locked in bridge can be extracted vTON-EVM Bridge · CertiK · 19 Jan 2023Open

TON contract `bridge_code` can `execute_voting()` received from the Bridge Governance (`multisig-code` owned by a set of oracles). According to the [ETH-TON bridge description](https://github.com/ton-blockchain/TIPs/issues/24#issuecomment-899768466), each oracle puts a significant amount of TON coins (stake) on the governing smart contract (`multisig-code`). The initial stake is 100k TON coins per oracle. Solidity contract `Bridge` can mint TONCOINs via `voteForMinting()`. In case of oracles collusion: 1. They can mint unlimited amount of ERC20 TONCOINs and sell them on DEX/CEX. The profit depends on the available liquidity and order book. 2. They can extract all the locked TONs from `bridge_code` via common "swap" operation. Reasonable if locked amount is bigger than the total stake. At the moment of writing total stake is 900k TONs, `total_locked` is 11M TONs. At the same time 1. The Bridge Governance can't be reassigned to another contract by Validators because that will automatically "unlock" the stakes. 2. Oracles set on ETH side can't be updated because it requires the signatures of old Bridge Governance participants. 3. If stakes unlocked, the oracles majority can steal minority's stakes. So, "out-of-control" Bridge can't be shut down. New Bridge has to be deployed and will work in parallel. The Bridge assumes that the majority of oracles follow the rules, despite the fact they are incentivized to do not. **Each oracle has to be trusted**, otherwise the malicious actor can stake from many accounts to get the majority.

Open the report
HighCentralization Related RisksTON Stablecoin · CertiK · 7 Dec 2022Open

The owner of `admin_address` is allowed to: * `op::mint` any amount of jettons to any wallet * `op::change_admin` to any other one * lock any wallet (prevent funds transferring) * transfer funds from any wallet to any other one or burn them * invalidate all the wallets, invalidate `total_supply` and other data * rename Jetton, change description or `decimals`

Open the report
MediumLack of `block.chainid` in signed data can lead tTON-EVM Bridge · CertiK · 19 Jan 2023Open

The message signed by oracles in one chain (Ethereum mainnet, BSC mainnet, Ethereum testnet, etc.) can be replayed by the attacker in another one, if the Bridge address is the same and oracle keys are the same. The replay attack can also be executed in case of chain fork (like Ethereum/Ethereum Classic).

Open the report
MediumOracles threshold is rounded downTON-EVM Bridge · CertiK · 19 Jan 2023Open

```solidity=19 require(signatures.length >= 2 * oraclesSet.length / 3, "Not enough signatures"); ``` The check is expected to pass if at least 2/3 or signatures were obtained. However, due to rounding down it can pass with less. For example, with 4 oracles only 2 signatures required.

Open the report
Low`active_flag` is stored in different waysTON-EVM Bridge · CertiK · 19 Jan 2023Open

`pending_queries` element has the one bit flag at the beginning. If it is set to 0, the query was already "executed". Otherwise the flag is 1 and other fields are packed in the structure. In `update_pending_queries()` this flag is saved with `store_uint()` and `store_int()`. In `message_signed_by_id?()`, `messages_by_mask()` and `unpack_query_data()` it is loaded by `load_int()`.

Open the report
Low`end_parse()` Is MissingTON-EVM Bridge · CertiK · 19 Jan 2023Open

`end_parse()` checks if slice is empty, otherwise throws an exception. It allows to ensure the slice has the expected data structure.

Open the report
Low`get_messages_unsigned_by_id()` name is misleadinTON-EVM Bridge · CertiK · 19 Jan 2023Open

According to the name the function `get_messages_unsigned_by_id()` should return the messages that are yet unsigned by the owner with `id`. However, the function returns the messages that were signed by that owner. `get_messages_unsigned()` returns all the messages not yet "executed".

Open the report
Low`load_text_hex_number()` should check the input dTON-EVM Bridge · CertiK · 19 Jan 2023Open

`load_text_hex_number()` doesn't perform some safety checks: 1. It is not checked that `comment.slice_bits()` is divisible by 8 (extra bits are ignored). 2. It is not checked that the result fits into `int` (overflow exception is thrown). 3. It is not checked that `comment` has enough data (underflow exception is thrown).

Open the report
Low`require()` can be usedTON-EVM Bridge · CertiK · 19 Jan 2023Open

The expression `if (!condition) revert(message)` can be rewritten in more common form `require(condition, message)`.

Open the report
Show 10 more
LowDeclaration Naming ConventionTON-EVM Bridge · CertiK · 19 Jan 2023Open

Some function names do not conform to the [Solidity style guide](https://solidity.readthedocs.io/en/v0.7.3/style-guide.html#naming-conventions) with regards to its naming convention.

Open the report
LowEthereum bridge `config_param(71)` is hardcodedTON-EVM Bridge · CertiK · 19 Jan 2023Open

`config_param(71)` stands for Ethereum mainnet bridge. To deploy the bridge for another chain one has to edit the code. This can lead to a confusion. Also, `multisig-code` and `bridge_code` use independent code to access the `config_param` which increases the code complexity.

Open the report
LowFunction Should Be Declared ExternalTON-EVM Bridge · CertiK · 19 Jan 2023Open

`public` functions which are never called internally within the contract should have `external` visibility for gas optimization. Unchanged `memory` arguments of `external` functions should be declared `calldata`.

Open the report
LowImproper Usage of `impure` ModifierTON-EVM Bridge · CertiK · 19 Jan 2023Open

The function `get_bridge_config()` is defined as `impure`, but it does not modify the storage or throw an exception.

Open the report
LowMissing event emittingTON-EVM Bridge · CertiK · 19 Jan 2023Open

`allowBurn` field is changed by `voteForSwitchBurn()` but no event is emitted.

Open the report
LowThe code can be simplifiedTON-EVM Bridge · CertiK · 19 Jan 2023Open

```cpp=15 throw_if(301, wc + 1); ``` The code can be rewritten in a more explicit way: ```cpp=15 throw_unless(301, wc == - 1); ``` ```cpp=67 int should_check = cnt_bits != old_cnt_bits; cnt -= should_check; ``` The code can be rewritten in a more explicit way: ```cpp=67 if (cnt_bits != old_cnt_bits) { cnt += 1; } ``` ```cpp=167 last_cleaned -= last_cleaned == 0; ``` The code can be rewritten in a more explicit way: ```cpp=167 if (last_cleaned == 0) { last_cleaned = 1; } ```

Open the report
LowUsage of Magic NumbersTON-EVM Bridge · CertiK · 19 Jan 2023Open

There are many magic numbers used directly in code.

Open the report
Low`losses` is not updated if there are no votes inTON Masterchain Contracts Formal Verification · CertiK · 14 Sep 2022Open

The voting configuration includes the parameters `min_wins` and `max_losses`, which are used to initialize new proposals. As we prove in this report, a proposal needs to win at least `min_wins` times in order to pass. If it loses more than `max_losses` times, it may be discarded. However, the latter is not a hard guarantee. The check for losses happens either when somebody votes for the proposal, or if the proposal is selected by the `scan_random_proposal()` function. If nobody voted on it for a long period of time, where the validator set changed multiple times and the proposal did not happen to be scanned, then the fact that it did not win in that period would not get recorded, so the loss count would be smaller and it could still pass.

Open the report
Low`uint` values are stored as `int`TON Vesting · CertiK · 5 Aug 2022Open

`seqno` and `subwallet_id` are saved into storage via `store_int()` but loaded via `load_uint()`. This can lead to exceptions in case of negative/too big values.

Open the report
LowCode DuplicationTON Vesting · CertiK · 5 Aug 2022Open

Loading data from the storage is done by the identical code several times. `locked_amount` calculation is done by the identical code two times.

Open the report
Show 2 more
LowFunction return value and argument types are notTON Vesting · CertiK · 5 Aug 2022Open

Function declarations contain `_` instead of real return type. Argument types are omitted.

Open the report
LowUsing of arbitrary integers in bitwise logical opTON Vesting · CertiK · 5 Aug 2022Open

`allow_elector` and `can_use_restricted` are 1-bit uint. However, they are used as part of logical expression. This can lead to accidental errors, like: ```c if (3 & 4) { ;; never happens } ```

Open the report

Contracts

No deployed address is recorded for these audits.

The reports name a repository or files. Open a report to see its scope.

The repositories and files the reports name

Show this on your site

Is this your project? Show this record on your own website. The label states what the record holds, links to this page and updates by itself. It is free and needs no sign-in.

Content

Facts

Automatic: the three strongest facts of this project’s own record (its last audit and two more), highlighted. They update with the record. Picking a fact turns Automatic off.

Fixed as
Language

Style

Layout
Theme
Accent
Corners

Format

Size
Date
Embed as
HTML
<head>
<script src="https://widget.trustblock.run/project-widget.min.js" defer></script>
</head>
<body>
<div
data-tb-project-widget
data-tb-project-slug="the-open-network"
></div>
</body>

Paste the code where the label should appear. It uses no API credit and updates by itself.

Something wrong on this page? A missing report, a wrong date, a finding that was fixed since. Tell us and we check it against its source.

Tell us