└── README.md /README.md: -------------------------------------------------------------------------------- 1 | # Checklist for Auditing TON Smart Contracts 2 | 3 | ## General 4 | 5 | - **Mapping Message Flows:** 6 | - Map all message flows of the contract to understand how messages are processed and routed. 7 | - **Key Questions:** 8 | - **Partial Execution of Transactions:** 9 | - What happens if a transaction is **partially executed** due to gas exhaustion? 10 | - How does the contract handle partial execution? 11 | - **Entry Points:** 12 | - Identify all **entry points** of the contract. 13 | - **Input Data Processing:** 14 | - How are **input data** and incoming messages processed? 15 | - Are incoming errors appropriately handled? 16 | - **Authorization Checks:** 17 | - Are there **authorization checks** for all functions and message handlers? 18 | - **Contract Design and Centralization:** 19 | - Examine the contract structure for any unnecessary **centralization**. 20 | - **External Message Handling:** 21 | - How does the contract handle **external messages**? 22 | - Ensure that `accept_message()` is used **only after** proper validations to prevent gas draining attacks. 23 | - Verify the implementation of `recv_external`. 24 | - **Preventing Freezing and Deletion:** 25 | - What mechanisms are in place to prevent the contract from being **frozen** or **deleted**? 26 | 27 | ## Asynchronous Execution 28 | 29 | - **Understanding Asynchrony:** 30 | - **Message Delivery Guarantees:** 31 | - Messages are guaranteed to be delivered but not in a predictable timeframe. 32 | - **Message Order Uncertainty:** 33 | - The order of messages can only be predicted if messages are sent to the same contract, in which case [logical time](https://docs.ton.org/develop/smart-contracts/guidelines/message-delivery-guarantees#what-is-a-logical-time) is used. 34 | - If multiple messages are sent to different contracts, the order in which they are received is not guaranteed. 35 | - **Key Considerations:** 36 | - **Concurrent Processes:** 37 | - What happens if another process runs in parallel? 38 | - How can this affect the contract, and how can it be mitigated? 39 | - **State Changes Between Messages:** 40 | - Can any required values change between message flows? 41 | - **External Dependencies:** 42 | - On which parameters or states of other contracts does this contract rely? 43 | - **Operation Independence:** 44 | - Ensure that operations are independent of the sequence of message arrivals. 45 | 46 | ## Common errors in TON 47 | 48 | ### What to look out for 49 | 50 | - **The public nature of blockchain:** 51 | - All data that is transmitted in a message is public and available to everyone 52 | - You can't send passwords, keys, and so on to the blockchain 53 | - **Bounced message handlers:** 54 | - If there was no such processing in Jetton, you could send tokens to the void. The [TON Stablecoin](https://github.com/ton-blockchain/stablecoin-contract) project has a [processing](https://github.com/ton-blockchain/stablecoin-contract/blob/main/contracts/jetton-minter.fc#L62-L73) bounced `op::internal_transfer` message that is sent to the Jetton wallet when minting tokens. If there is no processing, then `total_supply` will increase at minting and will be irrelevant since the tokens have not arrived on the wallet and they cannot be in circulation. 55 | - **Restrictions on data recording:** 56 | - **Unrestricted data recording:** 57 | - Is there a risk of **unlimited data writing** to the contract? 58 | - Avoid patterns that result in infinite data growth, such as infinite sharding. 59 | - **Tokenization:** 60 | - Tokenize assets or data into separate contracts if necessary. 61 | - **Logical errors:** 62 | - Errors in formulas, algorithms, and data structures are common. For example, if you perform division first and then multiplication, you may lose calculation accuracy and get a rounding error 63 | - `let result: Int = x / z * y;` 64 | - Standard errors 65 | - Code duplication 66 | - Unreachable code 67 | - Redundant code 68 | - Inefficient algorithms (on gas) 69 | - Inappropriate order of expressions in conditional statements 70 | - Errors in data parsing 71 | - Constant conditions in `if` 72 | - **Replay Attack:** 73 | - You can protect yourself with `seqno` (one-time numbers) 74 | - [Checks `seqno`](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/wallet3-code.fc#L15) 75 | - [Signature Checked](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/wallet3-code.fc#L17) 76 | - [**Carry-Value Pattern**](https://docs.ton.org/develop/smart-contracts/security/secure-programming#4-use-a-carry-value-pattern) 77 | - Transferring a value between contracts 78 | - The sender subtracts `amount` from its balance and sends it with `op::internal_transfer`. 79 | - The receiver takes the `amount` via message and adds it to its own balance (or rejects it). 80 | - In TON, it is not possible to get actual data via a request, because by the time the response reaches the requestor, the data may no longer be up to date. 81 | - **Smart Contract Update:** 82 | - **Storage compatibility:** 83 | - Ensure that updates do not break existing storage logic (watch out for `storage` collisions). 84 | - The `set_code` and `set_data` functions are used to update the `c3` and `c4` registers, and can completely overwrite the registers 85 | - **Delayed code updates:** 86 | - Realize that code updates do not affect the current transaction: 87 | - Changes take effect **only after** the current execution has successfully completed. 88 | - **Decentralization Issues:** 89 | - Evaluate how updates may affect the decentralization of the contract. 90 | - **Use of signed and unsigned numbers:** 91 | - If `int x` is sent in a message and `x` is added to `uint y` in the code, it is possible for the expression `x + y` to become `x - y` 92 | - **Exit codes:** 93 | - The use of reserved exit codes can cause confusion when handling errors 94 | - TON Blockchain reserved exit code values from 0 to 127 95 | - [TVM exit codes](https://docs.ton.org/v3/documentation/tvm/tvm-exit-codes) 96 | - Tact [utilizes](https://docs.tact-lang.org/book/exit-codes/) exit codes from 128 to 255 97 | - **Sending messages from a loop:** 98 | - A loop can be infinite or have too many iterations, which can lead to unpredictable contract behavior. 99 | - Continuous looping without completion can lead to an out-of-gas attack. 100 | - Attackers can use unlimited loops to create denial-of-service attacks. 101 | - **Parsing and serialization:** 102 | - Use `end_parse()` whenever possible when reading data from storage or message payloads to ensure that parsing completes correctly. 103 | 104 | ### Sending messages 105 | 106 | - **Check Flags:** 107 | - Verify that all keys and magic numbers match the contract logic when generating the message. 108 | - Make sure flags are not duplicated. 109 | - **Resource Management:** 110 | - Check that the message parameters do not excessively deplete the contract balance, especially for storage payments. 111 | - Sending a message with `mode=SendRemainingValue`/`mode=64` or `mode=128` will cause the operations following that message to fail. 112 | - The [documentation](https://docs.ton.org/v3/documentation/smart-contracts/message-management/message-modes-cookbook) is the best way to understand how messages are generated. 113 | 114 | ### Gas Control 115 | 116 | - **Moderate handling of gas:** 117 | - **Calculation of costs:** 118 | - Carefully calculate gas costs and verify that there is enough gas to operate. 119 | - **Data Structures:** 120 | - Be careful of data structures that can grow **infinitely** as they increase gas costs over time. 121 | - **Return excess gas:** 122 | - Implement logic to return **excess gas** to the sender when appropriate. 123 | - Failure to refund excess gas amounts paid can result in a buildup in the contract. 124 | - **Partial fulfillment risks:** 125 | - Recognize that running out of gas results in **partial performance**, which can lead to critical issues. 126 | - **Storage Parsing Efficiency:** 127 | - Avoid parsing and repacking the entire storage in each function call to reduce gas consumption. 128 | - Use nested storage. 129 | 130 | ### Random number generation in TON 131 | 132 | - **Safe randomness generation** 133 | - Validators can affect randomness 134 | - Hackers can figure out the formula for generating randomness. 135 | - [Be smart about randomness generation](https://docs.ton.org/v3/guidelines/smart-contracts/security/random-number-generation) 136 | - [Randomness in Tact](https://docs.tact-lang.org/cookbook/random/) 137 | - [Lessons on developing smart contracts on FunC “Random in TON”](https://github.com/romanovichim/TonFunClessons_Eng/blob/main/lessons/bonus/random/random.md) 138 | - **Pay attention to the use of:** 139 | - `random()` in FunC requires `randomize_lt()` or `randomize(x)` 140 | - `nativeRandom` or `nativeRandomInterval` in Tact instead of `randomInt` and `random` respectively 141 | 142 | ## Possible errors in FunC 143 | 144 | - **Function modifiers:** 145 | - Are all important functions correctly labeled with the `impure` modifier if they change state? 146 | - **Modifying variables:** 147 | - Review [modifying and non-modifying methods](https://docs.ton.org/develop/func/statements#methods-calls). 148 | - **Storage management:** 149 | - **Variable ordering:** 150 | - Verify the correct ordering of variables when packing into the repository. 151 | - **Manual storage management:** 152 | - Remember that the developer manually manages the storage and the data in the `c4` register is completely overwritten. 153 | - **Variable overrides:** 154 | - Check if state variables can be overwritten due to variable name collisions or namespace contamination. 155 | - This is possible [due to redeclaration](https://docs.ton.org/v3/documentation/smart-contracts/func/docs/statements#variable-declaration) of variables in FunC 156 | - **Nested Storage:** 157 | - Consider using nested storage (variables within variables) for better organization. 158 | 159 | ### Third-Party Code Execution 160 | 161 | - **Avoid External Code Execution:** 162 | - **Safety Risks:** 163 | - Executing third-party code is unsafe because `out of gas` exceptions cannot be caught with `CATCH`. 164 | - **Potential Exploits:** 165 | - An attacker could use `COMMIT` to alter the contract state before raising an `out of gas` exception. 166 | - **Best Practices:** 167 | - Keep contract logic self-contained and avoid incorporating untrusted external code. 168 | 169 | ## Possible errors in Tact 170 | 171 | - **Modifying the parameters of an incoming message or function:** 172 | - In Tact, function arguments are passed by value, which means that any mutations applied to these arguments will only affect the local copy of the variable within the function. 173 | - **Use of assembler:** 174 | - The use of TVM Assembly is a potentially dangerous operation that requires additional attention from the auditor. 175 | - **Use of native functions:** 176 | - Potentially dangerous operation requiring additional attention of the auditor. 177 | - **Double initialization of variables:** 178 | - The language allows initializing state variables at declaration time, but it is better to initialize variables in `init()` to avoid such errors 179 | - If this happens, the value from `init()` will be stored in the contract 180 | - **Direct modification of inherited variables:** 181 | - Variables from `trait` may have their own update rules, so direct modification may violate the contract invariant. 182 | - **Variables with optional value:** 183 | - If a developer creates an optional variable or field, they should use its functionality by referring to a null value somewhere in the code. 184 | - Otherwise, the optional type should be removed to simplify and optimize the code. 185 | 186 | ## Additional Recommendations 187 | 188 | - **Magic numbers, flags, and constants:** 189 | - Replace magic numbers with named constants for clarity and ease of maintenance. 190 | - **Documentation:** 191 | - Maintain clear and thorough documentation of the contract's functionality and design decisions. 192 | - **Code Review:** 193 | - Have the contract code reviewed by independent auditors to catch potential issues. 194 | - **Compliance with Standards:** 195 | - Ensure the contract adheres to relevant TON standards and best practices. 196 | 197 | By following this checklist, you can systematically assess the security and robustness of TON smart contracts, identifying potential vulnerabilities and ensuring reliable operation within the TON ecosystem. 198 | --------------------------------------------------------------------------------