ton-vulnerability-scanner
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseTON Vulnerability Scanner
TON漏洞扫描工具
1. Purpose
1. 用途
Systematically scan TON blockchain smart contracts written in FunC for platform-specific security vulnerabilities related to boolean logic, Jetton token handling, and gas management. This skill encodes 3 critical vulnerability patterns unique to TON's architecture.
系统性扫描TON区块链上使用FunC编写的智能合约,检测与布尔逻辑、Jetton代币处理及燃气管理相关的平台特定安全漏洞。本工具涵盖了3种TON架构特有的关键漏洞模式。
2. When to Use This Skill
2. 适用场景
- Auditing TON smart contracts (FunC language)
- Reviewing Jetton token implementations
- Validating token transfer notification handlers
- Pre-launch security assessment of TON dApps
- Reviewing gas forwarding logic
- Assessing boolean condition handling
- 审计TON智能合约(FunC语言)
- 审核Jetton代币实现方案
- 验证代币转账通知处理逻辑
- TON去中心化应用上线前的安全评估
- 审核燃气转发逻辑
- 评估布尔条件处理机制
3. Platform Detection
3. 平台检测
File Extensions & Indicators
文件扩展名与识别标识
- FunC files: ,
.fc.func
- FunC文件:、
.fc.func
Language/Framework Markers
语言/框架标记
func
;; FunC contract indicators
#include "imports/stdlib.fc";
() recv_internal(int my_balance, int msg_value, cell in_msg_full, slice in_msg_body) impure {
;; Contract logic
}
() recv_external(slice in_msg) impure {
;; External message handler
}
;; Common patterns
send_raw_message()
load_uint(), load_msg_addr(), load_coins()
begin_cell(), end_cell(), store_*()
transfer_notification operation
op::transfer, op::transfer_notification
.store_uint().store_slice().store_coins()func
;; FunC合约标识
#include "imports/stdlib.fc";
() recv_internal(int my_balance, int msg_value, cell in_msg_full, slice in_msg_body) impure {
;; 合约逻辑
}
() recv_external(slice in_msg) impure {
;; 外部消息处理函数
}
;; 常见模式
send_raw_message()
load_uint(), load_msg_addr(), load_coins()
begin_cell(), end_cell(), store_*()
transfer_notification 操作
op::transfer, op::transfer_notification
.store_uint().store_slice().store_coins()Project Structure
项目结构
- - FunC contract source
contracts/*.fc - - TypeScript wrappers
wrappers/*.ts - - Contract tests
tests/*.spec.ts - or
ton.config.ts- TON project configwasm.config.ts
- - FunC合约源码
contracts/*.fc - - TypeScript包装器
wrappers/*.ts - - 合约测试用例
tests/*.spec.ts - 或
ton.config.ts- TON项目配置文件wasm.config.ts
Tool Support
工具支持
- TON Blueprint: Development framework for TON
- toncli: CLI tool for TON contracts
- ton-compiler: FunC compiler
- Manual review primarily (limited automated tools)
- TON Blueprint:TON开发框架
- toncli:TON合约CLI工具
- ton-compiler:FunC编译器
- 主要以人工审核为主(自动化工具有限)
4. How This Skill Works
4. 工作机制
When invoked, I will:
- Search your codebase for FunC/Tact contracts
- Analyze each contract for the 3 vulnerability patterns
- Report findings with file references and severity
- Provide fixes for each identified issue
- Check replay protection and sender validation
调用本工具后,我会:
- 搜索代码库中的FunC/Tact合约
- 分析每份合约是否存在3种漏洞模式
- 输出检测结果,包含文件引用和漏洞严重等级
- 提供修复方案针对每个发现的问题
- 检查重放保护和发送方验证机制
5. Example Output
5. 输出示例
When vulnerabilities are found, you'll get a report like this:
=== TON VULNERABILITY SCAN RESULTS ===
Project: my-ton-contract
Files Scanned: 3 (.fc, .tact)
Vulnerabilities Found: 2
---
[CRITICAL] Missing Replay Protection
File: contracts/wallet.fc:45
Pattern: No sequence number or nonce validation
---当检测到漏洞时,你会收到如下格式的报告:
=== TON漏洞扫描结果 ===
项目:my-ton-contract
扫描文件数:3个(.fc、.tact)
发现漏洞数:2个
---
[CRITICAL] 缺失重放保护
文件:contracts/wallet.fc:45
模式:未验证序列号或随机数
---5. Vulnerability Patterns (3 Patterns)
5. 漏洞模式(3种)
I check for 3 critical vulnerability patterns unique to TON. For detailed detection patterns, code examples, mitigations, and testing strategies, see VULNERABILITY_PATTERNS.md.
我会检查TON特有的3种关键漏洞模式。如需详细的检测模式、代码示例、修复方案和测试策略,请查看VULNERABILITY_PATTERNS.md。
Pattern Summary:
模式摘要:
- Missing Sender Check ⚠️ CRITICAL - No sender validation on privileged operations
- Integer Overflow ⚠️ CRITICAL - Unchecked arithmetic in FunC
- Improper Gas Handling ⚠️ HIGH - Insufficient gas reservations
For complete vulnerability patterns with code examples, see VULNERABILITY_PATTERNS.md.
- 缺失发送方校验 ⚠️ 严重 - 特权操作未验证发送方
- 整数溢出 ⚠️ 严重 - FunC中存在未校验的算术操作
- 燃气处理不当 ⚠️ 高风险 - 燃气预留不足
如需包含代码示例的完整漏洞模式说明,请查看VULNERABILITY_PATTERNS.md。
5. Scanning Workflow
5. 扫描流程
Step 1: Platform Identification
步骤1:平台识别
- Verify FunC language (or
.fcfiles).func - Check for TON Blueprint or toncli project structure
- Locate contract source files
- Identify Jetton-related contracts
- 验证FunC语言(或
.fc文件).func - 检查是否为TON Blueprint或toncli项目结构
- 定位合约源码文件
- 识别与Jetton相关的合约
Step 2: Boolean Logic Review
步骤2:布尔逻辑审核
bash
undefinedbash
undefinedFind boolean-like variables
查找类布尔变量
rg "int.*is_|int.*has_|int.*flag|int.*enabled" contracts/
rg "int.*is_|int.*has_|int.*flag|int.*enabled" contracts/
Check for positive integers used as booleans
检查用作布尔值的正整数
rg "= 1;|return 1;" contracts/ | grep -E "is_|has_|flag|enabled|valid"
rg "= 1;|return 1;" contracts/ | grep -E "is_|has_|flag|enabled|valid"
Look for NOT operations on boolean-like values
查找类布尔值的取反操作
rg ".*(| " contracts/
For each boolean:
- [ ] Uses -1 for true, 0 for false
- [ ] NOT using 1 or other positive integers
- [ ] Logic operations work correctlyrg ".*(| " contracts/
针对每个布尔值:
- [ ] 使用-1表示真,0表示假
- [ ] 未使用1或其他正整数
- [ ] 逻辑运算正常工作Step 3: Jetton Handler Analysis
步骤3:Jetton处理函数分析
bash
undefinedbash
undefinedFind transfer_notification handlers
查找transfer_notification处理函数
rg "transfer_notification|op::transfer_notification" contracts/
For each Jetton handler:
- [ ] Validates sender address
- [ ] Sender checked against stored Jetton wallet address
- [ ] Cannot trust forward_payload without sender validation
- [ ] Has admin function to set Jetton wallet addressrg "transfer_notification|op::transfer_notification" contracts/
针对每个Jetton处理函数:
- [ ] 验证发送方地址
- [ ] 发送方与存储的Jetton钱包地址匹配
- [ ] 未在未验证发送方的情况下信任forward_payload
- [ ] 存在设置Jetton钱包地址的管理员函数Step 4: Gas/Forward Amount Review
步骤4:燃气/转账金额审核
bash
undefinedbash
undefinedFind forward amount usage
查找转账金额使用情况
rg "forward_ton_amount|forward_amount" contracts/
rg "load_coins()" contracts/
rg "forward_ton_amount|forward_amount" contracts/
rg "load_coins()" contracts/
Find send_raw_message calls
查找send_raw_message调用
rg "send_raw_message" contracts/
For each outgoing message:
- [ ] Forward amounts are fixed/bounded
- [ ] OR user-provided amounts validated against msg_value
- [ ] Cannot drain contract balance
- [ ] Appropriate send_raw_message flags usedrg "send_raw_message" contracts/
针对每个外发消息:
- [ ] 转账金额为固定值/有上限
- [ ] 或用户提供的金额已验证:`msg_value >= tx_fee + forward_amount`
- [ ] 合约余额不会被耗尽
- [ ] 使用了合适的send_raw_message标记Step 5: Manual Review
步骤5:人工审核
TON contracts require thorough manual review:
- Boolean logic with ,
~,&operators| - Message parsing and validation
- Gas economics and fee calculations
- Storage operations and data serialization
TON合约需要全面的人工审核:
- 使用、
~、&运算符的布尔逻辑| - 消息解析与验证
- 燃气经济性与费用计算
- 存储操作与数据序列化
6. Reporting Format
6. 报告格式
Finding Template
漏洞发现模板
markdown
undefinedmarkdown
undefined[CRITICAL] Fake Jetton Contract - Missing Sender Validation
[CRITICAL] 伪造Jetton合约 - 缺失发送方校验
Location: (recv_internal, transfer_notification handler)
contracts/staking.fc:85-95Description:
The operation handler does not validate that the sender is the expected Jetton wallet contract. Any attacker can send a fake message claiming to have transferred tokens, crediting themselves without actually depositing any Jettons.
transfer_notificationtransfer_notificationVulnerable Code:
func
// staking.fc, line 85
if (op == op::transfer_notification) {
int jetton_amount = in_msg_body~load_coins();
slice from_user = in_msg_body~load_msg_addr();
;; WRONG: No validation of sender_address!
;; Attacker can claim any jetton_amount
credit_user(from_user, jetton_amount);
}Attack Scenario:
- Attacker deploys malicious contract
- Malicious contract sends message to staking contract
transfer_notification - Message claims attacker transferred 1,000,000 Jettons
- Staking contract credits attacker without checking sender
- Attacker can now withdraw from contract or gain benefits without depositing
Proof of Concept:
typescript
// Attacker sends fake transfer_notification
const attackerContract = await blockchain.treasury("attacker");
await stakingContract.sendInternalMessage(attackerContract.getSender(), {
op: OP_CODES.TRANSFER_NOTIFICATION,
jettonAmount: toNano("1000000"), // Fake amount
fromUser: attackerContract.address,
});
// Attacker successfully credited without sending real Jettons
const balance = await stakingContract.getUserBalance(attackerContract.address);
expect(balance).toEqual(toNano("1000000")); // Attack succeededRecommendation:
Store expected Jetton wallet address and validate sender:
func
global slice jetton_wallet_address;
() recv_internal(...) impure {
load_data(); ;; Load jetton_wallet_address from storage
slice cs = in_msg_full.begin_parse();
int flags = cs~load_uint(4);
slice sender_address = cs~load_msg_addr();
int op = in_msg_body~load_uint(32);
if (op == op::transfer_notification) {
;; CRITICAL: Validate sender
throw_unless(error::wrong_jetton_wallet,
equal_slices(sender_address, jetton_wallet_address));
int jetton_amount = in_msg_body~load_coins();
slice from_user = in_msg_body~load_msg_addr();
;; Safe to credit user
credit_user(from_user, jetton_amount);
}
}References:
- building-secure-contracts/not-so-smart-contracts/ton/fake_jetton_contract
---位置:(recv_internal,transfer_notification处理函数)
contracts/staking.fc:85-95描述:
操作处理函数未验证发送方是否为预期的Jetton钱包合约。攻击者可发送伪造的消息,声称已转账代币,无需实际存入Jetton即可给自己增加额度。
transfer_notificationtransfer_notification漏洞代码:
func
// staking.fc,第85行
if (op == op::transfer_notification) {
int jetton_amount = in_msg_body~load_coins();
slice from_user = in_msg_body~load_msg_addr();
;; 错误:未验证sender_address!
;; 攻击者可以声称任意jetton_amount
credit_user(from_user, jetton_amount);
}攻击场景:
- 攻击者部署恶意合约
- 恶意合约向质押合约发送消息
transfer_notification - 消息声称攻击者已转账1,000,000个Jetton
- 质押合约未检查发送方就给攻击者增加额度
- 攻击者无需存入代币即可从合约提取资金或获取权益
概念验证:
typescript
// 攻击者发送伪造的transfer_notification
const attackerContract = await blockchain.treasury("attacker");
await stakingContract.sendInternalMessage(attackerContract.getSender(), {
op: OP_CODES.TRANSFER_NOTIFICATION,
jettonAmount: toNano("1000000"), // 伪造金额
fromUser: attackerContract.address,
});
// 攻击者成功获得额度,无需发送真实Jetton
const balance = await stakingContract.getUserBalance(attackerContract.address);
expect(balance).toEqual(toNano("1000000")); // 攻击成功修复建议:
存储预期的Jetton钱包地址并验证发送方:
func
global slice jetton_wallet_address;
() recv_internal(...) impure {
load_data(); ;; 从存储中加载jetton_wallet_address
slice cs = in_msg_full.begin_parse();
int flags = cs~load_uint(4);
slice sender_address = cs~load_msg_addr();
int op = in_msg_body~load_uint(32);
if (op == op::transfer_notification) {
;; 关键:验证发送方
throw_unless(error::wrong_jetton_wallet,
equal_slices(sender_address, jetton_wallet_address));
int jetton_amount = in_msg_body~load_coins();
slice from_user = in_msg_body~load_msg_addr();
;; 可安全地给用户增加额度
credit_user(from_user, jetton_amount);
}
}参考:
- building-secure-contracts/not-so-smart-contracts/ton/fake_jetton_contract
---7. Priority Guidelines
7. 优先级指南
Critical (Immediate Fix Required)
严重(需立即修复)
- Fake Jetton contract (unauthorized minting/crediting)
- 伪造Jetton合约(未授权铸造/增加额度)
High (Fix Before Launch)
高风险(上线前修复)
- Integer as boolean (logic errors, broken conditions)
- Forward TON without gas check (balance drainage)
- 整数当作布尔值使用(逻辑错误、条件失效)
- 未做燃气检查的TON转账(余额耗尽)
8. Testing Recommendations
8. 测试建议
Unit Tests
单元测试
typescript
import { Blockchain } from "@ton/sandbox";
import { toNano } from "ton-core";
describe("Security tests", () => {
let blockchain: Blockchain;
let contract: Contract;
beforeEach(async () => {
blockchain = await Blockchain.create();
contract = blockchain.openContract(await Contract.fromInit());
});
it("should use correct boolean values", async () => {
// Test that TRUE = -1, FALSE = 0
const result = await contract.getFlag();
expect(result).toEqual(-1n); // True
expect(result).not.toEqual(1n); // Not 1!
});
it("should reject fake jetton transfer", async () => {
const attacker = await blockchain.treasury("attacker");
const result = await contract.send(
attacker.getSender(),
{ value: toNano("0.05") },
{
$$type: "TransferNotification",
query_id: 0n,
amount: toNano("1000"),
from: attacker.address,
}
);
expect(result.transactions).toHaveTransaction({
success: false, // Should reject
});
});
it("should validate gas for forward amount", async () => {
const result = await contract.send(
user.getSender(),
{ value: toNano("0.01") }, // Insufficient gas
{
$$type: "Transfer",
to: recipient.address,
forward_ton_amount: toNano("1"), // Trying to forward 1 TON
}
);
expect(result.transactions).toHaveTransaction({
success: false,
});
});
});typescript
import { Blockchain } from "@ton/sandbox";
import { toNano } from "ton-core";
describe("安全测试", () => {
let blockchain: Blockchain;
let contract: Contract;
beforeEach(async () => {
blockchain = await Blockchain.create();
contract = blockchain.openContract(await Contract.fromInit());
});
it("应使用正确的布尔值", async () => {
// 测试TRUE = -1,FALSE = 0
const result = await contract.getFlag();
expect(result).toEqual(-1n); // 真
expect(result).not.toEqual(1n); // 不能是1!
});
it("应拒绝伪造的Jetton转账", async () => {
const attacker = await blockchain.treasury("attacker");
const result = await contract.send(
attacker.getSender(),
{ value: toNano("0.05") },
{
$$type: "TransferNotification",
query_id: 0n,
amount: toNano("1000"),
from: attacker.address,
}
);
expect(result.transactions).toHaveTransaction({
success: false, // 应拒绝
});
});
it("应验证转账金额的燃气", async () => {
const result = await contract.send(
user.getSender(),
{ value: toNano("0.01") }, // 燃气不足
{
$$type: "Transfer",
to: recipient.address,
forward_ton_amount: toNano("1"), // 尝试转账1个TON
}
);
expect(result.transactions).toHaveTransaction({
success: false,
});
});
});Integration Tests
集成测试
typescript
// Test with real Jetton wallet
it("should accept transfer from real jetton wallet", async () => {
// Deploy actual Jetton minter and wallet
const jettonMinter = await blockchain.openContract(JettonMinter.create());
const userJettonWallet = await jettonMinter.getWalletAddress(user.address);
// Set jetton wallet in contract
await contract.setJettonWallet(userJettonWallet);
// Real transfer from Jetton wallet
const result = await userJettonWallet.sendTransfer(
user.getSender(),
contract.address,
toNano("100"),
{}
);
expect(result.transactions).toHaveTransaction({
to: contract.address,
success: true,
});
});typescript
// 使用真实Jetton钱包测试
it("应接受来自真实Jetton钱包的转账", async () => {
// 部署实际的Jetton铸造器和钱包
const jettonMinter = await blockchain.openContract(JettonMinter.create());
const userJettonWallet = await jettonMinter.getWalletAddress(user.address);
// 在合约中设置Jetton钱包
await contract.setJettonWallet(userJettonWallet);
// 从Jetton钱包发起真实转账
const result = await userJettonWallet.sendTransfer(
user.getSender(),
contract.address,
toNano("100"),
{}
);
expect(result.transactions).toHaveTransaction({
to: contract.address,
success: true,
});
});9. Additional Resources
9. 额外资源
- Building Secure Contracts:
building-secure-contracts/not-so-smart-contracts/ton/ - TON Documentation: https://docs.ton.org/
- FunC Documentation: https://docs.ton.org/develop/func/overview
- TON Blueprint: https://github.com/ton-org/blueprint
- Jetton Standard: https://github.com/ton-blockchain/TEPs/blob/master/text/0074-jettons-standard.md
- Building Secure Contracts:
building-secure-contracts/not-so-smart-contracts/ton/ - TON文档:https://docs.ton.org/
- FunC文档:https://docs.ton.org/develop/func/overview
- TON Blueprint:https://github.com/ton-org/blueprint
- Jetton标准:https://github.com/ton-blockchain/TEPs/blob/master/text/0074-jettons-standard.md
10. Quick Reference Checklist
10. 快速参考检查清单
Before completing TON contract audit:
Boolean Logic (HIGH):
- All boolean values use -1 (true) and 0 (false)
- NO positive integers (1, 2, etc.) used as booleans
- Functions returning booleans return -1 for true
- Boolean logic with ,
~,&uses correct values| - Tests verify boolean operations work correctly
Jetton Security (CRITICAL):
- handler validates sender address
transfer_notification - Sender checked against stored Jetton wallet address
- Jetton wallet address stored during initialization
- Admin function to set/update Jetton wallet
- Cannot trust forward_payload without sender validation
- Tests with fake Jetton contracts verify rejection
Gas & Forward Amounts (HIGH):
- Forward TON amounts are fixed/bounded
- OR user-provided amounts validated:
msg_value >= tx_fee + forward_amount - Contract balance protected from drainage
- Appropriate flags used
send_raw_message - Tests verify cannot drain contract with excessive forward amounts
Testing:
- Unit tests for all three vulnerability types
- Integration tests with real Jetton contracts
- Gas cost analysis for all operations
- Testnet deployment before mainnet
完成TON合约审计前需检查:
布尔逻辑(高风险):
- 所有布尔值使用-1(真)和0(假)
- 未使用正整数(1、2等)当作布尔值
- 返回布尔值的函数使用-1表示真
- 使用、
~、&的布尔逻辑使用正确的值| - 测试验证布尔运算正常工作
Jetton安全(严重):
- 处理函数验证发送方地址
transfer_notification - 发送方与存储的Jetton钱包地址匹配
- Jetton钱包地址在初始化时存储
- 存在设置/更新Jetton钱包的管理员函数
- 未在未验证发送方的情况下信任forward_payload
- 使用伪造Jetton合约的测试验证了拒绝逻辑
燃气与转账金额(高风险):
- TON转账金额为固定值/有上限
- 或用户提供的金额已验证:
msg_value >= tx_fee + forward_amount - 合约余额不会被耗尽
- 使用了合适的标记
send_raw_message - 测试验证无法通过超额转账耗尽合约余额
测试:
- 针对3种漏洞类型的单元测试
- 使用真实Jetton合约的集成测试
- 所有操作的燃气成本分析
- 主网上线前部署到测试网