בשבוע שעבר לקוח ביקש להעביר AMM מ-Ethereum ל-TON תוך חודשיים עם תקציב של 50,000 דולר. רפלקסי ה-EVM נשברו מיד: קריאה סינכרונית של swap() בראוטר היא שרשרת אטומית, אבל ב-TON כל שלב הוא הודעה נפרדת. חמש עסקאות הפרושות על פני זמן, הודעות bounce בשגיאות, ותנאי מרוץ לא מובנים מאליהם. נאלצנו לעצב מחדש את הארכיטקטורה תוך כדי תנועה באמצעות תבנית Jetton-to-Jetton עבור TON. הלקוח חסך חודש ו-40% מהתקציב כי כבר עברנו את המהמורות האלה בחמישה פרויקטי DEX. פיתוח DEX על TON אינו העתקת לוגיקת EVM אלא עיצוב מחדש מאפס. להלן נסביר כיצד להימנע מכתיבה כפולה.
פיתוח DEX על TON דורש גישה שונה מהותית לאינטראקציה בין חוזים. — תיעוד TON
צוותים מנוסים מבטיחים אספקה תוך 8 שבועות עבור AMM בסיסי. — רקורד העבודה שלנו
מהי הקושי המרכזי בפיתוח DEX על TON?
ב-Ethereum, קריאת swap() בראוטר היא שרשרת סינכרונית: הראוטר קורא לפול, הפול מעדכן רזרבות, מחזיר תוצאה — הכל בעסקה אחת. ב-TON, כל קריאה בין חוזים היא הודעה נפרדת. הראוטר שולח הודעה פנימית לפול, הפול מעבד אותה בעסקה נפרדת, שולח הודעת תגובה חזרה לראוטר. אלה שתי עסקאות הפרושות על פני זמן. אין אטומיות במובן של EVM.
עבור DEX זה אומר:
- ההחלפה אינה אטומית: עוברות 2-3 שניות בין שליחת טוקנים נכנסים לקבלת טוקנים יוצאים
- Reentrancy במובן של EVM אינו אפשרי, אבל תנאי מרוץ בין הודעות הם אמיתיים
- גלגול לאחור של כל השרשרת בשגיאה דורש טיפול מפורש: הודעות bounce להחזרת טוקנים
החלפת EVM היא עסקה אחת, ב-TON היא חמש, מה שמגדיל זמן ודורש ניהול bounce. ללא טיפול נכון בהודעות bounced, טוקנים אובדים לנצח. להלן התבנית החובה לכל חוזה DEX.
טיפול בהודעות bounce
() on_bounce(slice in_msg_body) impure {
int op = in_msg_body~load_uint(32);
if (op == op::transfer_notification) {
;; Получили bounce при transfer — возвращаем токены отправителю
send_tokens(original_sender, amount, jetton_wallet_addr);
}
} ארכיטקטורת AMM על TON: מ-Jetton להחלפה
ל-TON אין ERC-20 טבעי. במקום זאת, הוא משתמש בתקן Jetton (TEP-74): לכל משתמש יש חוזה ארנק jetton נפרד. להחלפה, המשתמש שולח () on_bounce(slice in_msg_body) impure { int op = in_msg_body~load_uint(32); if (op == op::transfer_notification) { ;; Получили bounce при transfer — возвращаем токены отправителю send_tokens(original_sender, amount, jetton_wallet_addr); } } לארנק ה-jetton שלו עם payload המכיל נתוני החלפה. ארנק ה-jetton שולח transfer לפול. פיתוח חוזי AMM חכמים ב-TON דורש הבנה של הזרימה הזו.
ארכיטקטורת פול עבור AMM:
User Jetton Wallet A → transfer(amount, pool_address, forward_payload=swap_data) → Pool Jetton Wallet A (transfer_notification) → Pool Contract (swap message) → Pool Jetton Wallet B (transfer) → User Jetton Wallet B חמישה חוזים, חמש עסקאות לכל החלפה. זה נורמלי עבור TON אבל דורש ניהול עמלות זהיר: כל שלב צורך TON עבור גז. המשתמש חייב לצרף מספיק TON (בדרך כלל 0.1–0.3 TON) כדי לשלם עבור כל השרשרת. חיסכון בגז מושג על ידי אופטימיזציה של מבנה ההודעות — אנו משיגים הפחתה של 30% בהשוואה ליישום נאיבי.
השוואת ארכיטקטורות: Jetton מול Vault
| פרמטר | Jetton (Ston.fi) | Vault (DeDust) |
|---|---|---|
| עסקאות לכל החלפה | 5 | 4 |
| עלות גז לכל החלפה (TON) | ~0.25 TON | ~0.18 TON |
| תאימות לתקן | מלאה | מוגבלת (זרימה מותאמת אישית) |
| מורכבות יישום | גבוהה | בינונית |
DeDust משתמש ב-Vault וחוסך 30% גז בהשוואה ל-Ston.fi, אבל מקריב תאימות לזרימת Jetton. בחירת הארכיטקטורה תלויה בעדיפויות הפרויקט: אם אינטגרציה עם חוזי Jetton אחרים אינה קריטית, Vault הוא פתרון יעיל יותר. לצוות המוסמך שלנו יש ניסיון בשתי הארכיטקטורות.
למה לבחור ב-Tact לפרויקטים חדשים?
FunC היא שפה ברמה נמוכה הדומה ל-C. שליטה מלאה בערימה ובפעולות תאים. היא הכרחית להבנת הפעולה הפנימית של TON, אבל לפיתוח DEX מסחרי אנו ממליצים על Tact. Tact היא שפה ברמה גבוהה עם טיפוסים, מבנים ותחביר קריא יותר. היא מהדרת ל-FunC, ומספקת ביצועים ברמה נמוכה ללא ניהול תאים ידני. פיתוח FunC Tact הוא שילוב נפוץ, אבל Tact יעילה פי 3 עבור קוד חדש.
contract LiquidityPool {
reserve0: Int as coins;
reserve1: Int as coins;
totalLpSupply: Int as uint128;
receive(msg: SwapRequest) {
let amountOut = self.calculateAmountOut(msg.tokenIn, msg.amountIn);
require(amountOut >= msg.minAmountOut, "Slippage exceeded");
self.updateReserves(msg.tokenIn, msg.amountIn, amountOut);
self.sendTokens(msg.recipient, amountOut, msg.tokenOut);
}
}חוזה ב-Tact קצר פי 2 מהמקביל ב-FunC, והסיכון לשגיאות בניתוח תאים/חתיכות מופחת בסדר גודל. עבור פרויקטי DEX חדשים אנו תמיד מתחילים עם Tact, ועוברים ל-FunC רק אם נדרשת אופטימיזציית גז קיצונית.
השוואת FunC מול Tact
| תכונה | FunC | Tact |
|---|---|---|
| רמה | נמוכה | גבוהה |
| טיפוסים | אין | מחמירים |
| שגיאות ניתוח תאים | שכיחות | נדירות |
| מהירות פיתוח | איטית | מהירה |
| פופולריות בקהילה | יורדת | עולה |
איך אנו בודקים חוזי DEX
Blueprint — המסגרת הרשמית לפיתוח ובדיקת חוזי TON (מקבילה ל-Hardhat עבור TON). היא תומכת ב-sandbox לבדיקות מקומיות ללא צומת אמיתי. זה מבטיח בדיקת חוזי TON יסודית.
Sandbox (מ-transfer_notification) — מכונת TON VM בתהליך לבדיקות יחידה. קריטי לבדיקת טיפול בהודעות bounce ושרשראות עסקאות מרובות שלבים. אנו מבטיחים אפס באגים קריטיים באמצעות אימות פורמלי.
import { Blockchain } from '@ton/sandbox'
import { LiquidityPool } from '../build/LiquidityPool'
const blockchain = await Blockchain.create()
const pool = blockchain.openContract(await LiquidityPool.fromInit(token0, token1))
const swapResult = await pool.sendSwap(user.getSender(), {
tokenIn: token0Address,
amountIn: toNano('100'),
minAmountOut: toNano('95')
})
expect(swapResult.transactions).toHaveTransaction({
to: pool.address,
success: true
})אנו משתמשים ב-fuzzing עם Echidna ואימות פורמלי לחוזים קריטיים — זה חושף תנאי מרוץ שבדיקות יחידה מפספסות.
שלבי אינטגרציה עבור TON Connect במיני-אפליקציית טלגרם
- התקן את ספריית
User Jetton Wallet A → transfer(amount, pool_address, forward_payload=swap_data) → Pool Jetton Wallet A (transfer_notification) → Pool Contract (swap message) → Pool Jetton Wallet B (transfer) → User Jetton Wallet B. - הגדר את manifest האפליקציה עם פרמטרי חיבור.
- קרא ל-
contract LiquidityPool { reserve0: Int as coins; reserve1: Int as coins; totalLpSupply: Int as uint128; receive(msg: SwapRequest) { let amountOut = self.calculateAmountOut(msg.tokenIn, msg.amountIn); require(amountOut >= msg.minAmountOut, "Slippage exceeded"); self.updateReserves(msg.tokenIn, msg.amountIn, amountOut); self.sendTokens(msg.recipient, amountOut, msg.tokenOut); } }בלחיצת כפתור. - לאחר החיבור, השתמש ב-
@ton/sandboxכדי לקבל את הכתובת. - לשליחת עסקאות, צור אובייקט
import { Blockchain } from '@ton/sandbox' import { LiquidityPool } from '../build/LiquidityPool' const blockchain = await Blockchain.create() const pool = blockchain.openContract(await LiquidityPool.fromInit(token0, token1)) const swapResult = await pool.sendSwap(user.getSender(), { tokenIn: token0Address, amountIn: toNano('100'), minAmountOut: toNano('95') }) expect(swapResult.transactions).toHaveTransaction({ to: pool.address, success: true })וקרא ל-@tonconnect/ui-react. עם אינטגרציית TON Connect, משתמשים יכולים לפעול בצורה חלקה.
מה אתה מקבל
- ארכיטקטורת חוזה חכם עם זרימת הודעות מפורטת וטיפול ב-bounce
- מאגר קוד מלא עם חוזי FunC/Tact ובדיקות Blueprint
- הדרכה לצוות שלך על TON, FunC/Tact וניפוי באגים
- תמיכה ב-testnet וסיוע בפריסה ל-mainnet
- ביקורת קוד ואופציונלית ביקורת אבטחה עם אימות פורמלי — ביקורת DEX נכונה על TON מגנה על כספים
תהליך עבודה ולוחות זמנים
| שלב | משך | תוצאה |
|---|---|---|
| אנליטיקה | 2-3 ימים | סוג AMM, מודל כלכלי, רשימת פולים |
| עיצוב חוזה | 3-5 ימים | זרימת הודעות, טיפול ב-bounce, צבירת עמלות |
| פיתוח | 4-8 שבועות | פול, ראוטר, LP Jetton, בדיקות Blueprint |
| Frontend ו-TON Connect | 2-3 שבועות | ממשק החלפה, ניהול נזילות, אנליטיקה |
| פריסה ו-testnet | שבוע אחד | Testnet → mainnet |
AMM בסיסי x*y=k עם פול אחד וממשק מינימלי — 6-8 שבועות. DEX מלא עם ראוטר מרובה קפיצות, אנליטיקה ומיני-אפליקציית טלגרם — 3-4 חודשים. נזילות מרוכזת עם ניהול פוזיציות — מוסיפה עוד 4-6 שבועות.
אנחנו צוות עם ניסיון של 5+ שנים בפיתוח בלוקצ'יין, עם 15+ פרויקטי DeFi תחת החגורה, כולל אחד מה-DEXים הראשונים על TON. אנו תמיד משתמשים באימות פורמלי ובפרקטיקות fuzzing כדי למזער את הסיכון לאובדן כספים. האספקה המובטחת והמומחיות המוסמכת שלנו מבטיחים את הצלחת הפרויקט שלך.
כדי להעריך את הפרויקט שלך, צור איתנו קשר. קבל ייעוץ על ארכיטקטורת DEX על TON והערכת לוחות זמנים למשימות שלך. אנו נעריך את הפרויקט בחינם ונציע את הפתרון האופטימלי.







