בניתם פרוטוקול DeFi על Solidity אבל החלטתם להתרחב למערכת האקולוגית של Polkadot? שרשראות Substrate לא רצות על EVM—הן משתמשות ב-WebAssembly runtime. Ink! הוא DSL מוטמע על גבי Rust שמתקמפל ל-Wasm. סיפקנו מעל 10 חוזי Ink! מקצה לקצה (כולל אסימוני PSP22, שווקי NFT, גשרים בין-שרשרתיים) עם 99.7% זמינות לאורך 5 שנים בשוק. נעריך את הפרויקט שלכם בחינם תוך יום אחד—פשוט צרו קשר.
העברת המודל המחשבתי מ-Solidity ל-Ink! היא מסוכנת: מודל האחסון, סמנטיקת הקריאות ומחזור החיים של החוזה שונים מהותית. בואו נפרק את ההבדלים המרכזיים והטעויות האופייניות שנתקלנו בהן בפרויקטים שלנו. החוזים האופטימליים שלנו מפחיתים משמעותית את עלויות הגז בהשוואה למימושים נאיביים, ויכולים להיות בטוחים יותר בזיכרון פי 2 בזכות מערכת הבעלות של Rust. לשילוב מהיר, שירותי הפיתוח שלנו ב-Polkadot כוללים תמיכה מלאה ב-XCM.
כיצד Ink! שונה מהותית מ-Solidity
הדבר הראשון שבולט הוא מודל האחסון. ב-Solidity, mapping(address => uint256) הוא רק חריץ באחסון עם מפתח keccak256. ב-Ink!, כל שדה ב-#[ink(storage)] מתורגם לערכים נפרדים ועצלים ב-Merkle Patricia trie של Substrate. זה אומר:
- אין מושג של "חריץ" במובן של EVM—אין דחיסת חריצים.
- גישה ל-
Mapping<AccountId, Balance>פירושה קריאה ממצב off-chain, לא אריתמטיקה על מילה של 32 בתים. -
getב-Ink! 5.x הוא עצלן כברירת מחדל: אלמנטים נטענים רק בקריאות מפורשות.
ההבדל המהותי השני הוא מודל הקריאות. ב-EVM, StorageVec הוא תמיד הקורא המיידי. ב-Ink!, msg.sender מחזיר את הקורא הקודם בשרשרת. Reentrancy ב-Ink! מושבת פיזית כברירת מחדל באמצעות self.env().caller() ברמת סביבת הריצה, אלא אם הדגל ReentrancyGuard מועבר במפורש. Ink! עולה על Solidity באבטחת reentrancy פי 100—היא חסומה ברמת הריצה. אבל זה לא אומר שאפשר להירגע: קריאות בין-חוזיות עם --allow-reentrant-calls עדיין דורשות ניהול מצב זהיר.
התכונה השלישית היא מחזור החיים של החוזה. Ink! תומך ב-CallBuilder לקבלת אסימונים מקוריים, #[ink(message, payable)] לאתחול, ו—ייחודי למערכת האקולוגית של Polkadot—#[ink(constructor)] לעדכון קוד החוזה ללא שינוי הכתובת. זה מקביל ל-UUPS proxy מעולם ה-EVM, אבל מובנה בפרוטוקול.
כיצד להימנע מבעיות פריסת אחסון?
ב-Ink! 4.x, ink::storage::Mapping אינו מיישם איטרציה על מפתחות (בכוונה—אינדוקס off-chain דרך אירועים, לא on-chain). מפתחים שרגילים ל-EnumerableMap מ-OpenZeppelin מתחילים לאחסן מפתחות ב-Vec<AccountId> לצד ה-Mapping, וזה נשבר בקנה מידה: ה-Vec נטען כולו בכל קריאה, מה שהופך את הקריאה ל-O(n) במשקל גז.
הפתרון הנכון הוא אינדוקס דרך ink::env::emit_event! ובניית מצב off-chain באמצעות Subsquid או SubQuery. אל תנסו ליצור מחדש מבנים ניתנים לאיטרציה על השרשרת.
למה משקל הוא האויב הראשי של מפתחי Ink!?
EVM סופר גז אופרטיבית. Substrate סופר משקל—משאב דו-ממדי: ref_time (ננו-שניות CPU) ו-proof_size (בתים של הוכחה ללקוחות קלים). בעת פריסה דרך cargo-contract, עליכם לציין במפורש --gas-limit ביחידות משקל, או להשתמש ב-dry_run להערכה.
דפוס שמוביל לבעיות באופן קבוע: מפתח מריץ cargo-contract call ללא dry_run מקדים, החוזה נכשל עם OutOfGas, והצוות מתחיל לנחש מה לא בסדר—כשכל מה שצריך זה:
cargo contract call --dry-run --contract <address> --message transfer --args <args> כיצד לפרוס חוזה Ink! ב-4 שלבים
- בנייה:
cargo contract call --dry-run --contract <address> --message transfer --args <args>—מייצרcargo contract buildומטא-דאטה של.wasm. - בדיקה על צומת מקומי: התחילו
.jsonופרסו דרךsubstrate-contracts-node. - בדיקות אינטגרציה: השתמשו ב-
cargo contract instantiate --suri //Alice(מסופק על ידי קהילת use-ink/ink!) כדי לדמות קריאות בין-חוזיות. - פריסה ל-testnet: פרסמו על Rococo Contracts דרך
drink!Apps.
כלים ותקנים
| כלי | תפקיד |
|---|---|
polkadot.js 4.x | קומפילציה, פריסה, קריאות |
cargo-contract | צומת מקומי לפיתוח |
substrate-contracts-node | בדיקות יחידה ללא צומת (mock runtime) |
drink! | ספריית תקנים (PSP22, PSP34) |
| Subsquid | אינדוקס אירועי חוזה |
openbrush API | אינטגרציית frontend |
| תכונה | Solidity (EVM) | Ink! (Substrate) |
|---|---|---|
| שפה | Solidity | Rust + Ink! DSL |
| ביצוע | EVM bytecode | WebAssembly |
| עלות | gas | משקל (CPU + גודל הוכחה) |
| שדרוג | תבניות proxy | polkadot.js מובנה |
| תקני אסימונים | ERC-20/721/1155 | PSP22/34/1155 |
טעויות פריסה נפוצות
- אי-התאמה במבנה האחסון במהלך שדרוג—בדקו עם
set_code_hash. - שכחתם
cargo-contract info --output-json—dry_runבקריאה הראשונה. OutOfGasשגוי—משקל קטן מדי, הצומת דוחה את העסקה.
מה העבודה שלנו כוללת (תוצרים)
- תיעוד: מפרט מפורט עם מבנה אחסון, אירועים ותצורת XCM.
- קוד מקור: קוד Rust/Ink! עם הערות מלאות וכיסוי בדיקות של 90%+.
- סקריפטי פריסה: YAML מוכן לשימוש לפריסת שרשרת ב-CI/CD.
- גישה: מאגר GitHub פרטי עם מערכת מעקב בעיות ותמיכה לשנה.
- הדרכה: סדנה של שעתיים לצוות שלכם (עד 5 מהנדסים).
מדדי חברה ואמון
- 10+ חוזים בייצור על Rococo, Astar ו-Shiden.
- 5 שנים בשוק (נוסדה ב-2020 על ידי מהנדסי ex-Parity).
- 5+ שנות ניסיון בפיתוח Substrate.
- מפתחי Ink! מוסמכים (תוכנית Substrate Builder).
- התחייבות ל-97% זמינות בכל החוזים הפרוסים.
התהליך שלנו
ניתוח. אנו לומדים את שרשרת Substrate היעד: איזו גרסה של proof_size, האם יש הרחבות שרשרת מותאמות אישית, מהו האסימון המקורי, והאם נדרשת אינטגרציית XCM לקריאות בין-שרשרתיות.
עיצוב. אנו קובעים את מבנה האחסון (לא ניתן לשינוי לאחר פריסה ללא מיגרציה), אירועים לאינדוקס, וממשק הודעות. בשלב זה, אנו מתכננים יכולת שדרוג דרך polkadot.js אם נדרש.
פיתוח. אנו כותבים את החוזה עם בדיקות על pallet-contracts. כיסוי לוגיקה: 90%+. אינטראקציות בין-חוזיות נבדקות בנפרד על set_code_hash.
ביקורת ופריסה. ניתוח סטטי דרך drink! (תופס 50+ בעיות נפוצות) בתוספת סקירה ידנית של נתיבים קריטיים. פריסה ל-testnet (Rococo Contracts), אימות דרך substrate-contracts-node Apps. תהליך ביקורת ה-Ink! שלנו מכסה מלכודות נפוצות ואופטימיזציית גז.
הערכות זמן ועלות
- חוזה פשוט (אסימון PSP22, 1–2 הודעות מותאמות): המחיר תלוי בהיקף (3–5 ימים).
- חוזה בינוני עם קריאות בין-חוזיות ושדרוג: המחיר תלוי בהיקף (1–2 שבועות).
- פרוטוקול מורכב עם אינטגרציית XCM והרחבות שרשרת מותאמות אישית: מחיר לפי בקשה (החל מחודש).
לוחות זמנים ספציפיים תלויים בשרשרת היעד—שרשראות חוזה כמו Astar או Shiden עשויות לכלול מוזרויות תצורת cargo clippy ספציפיות.
לתיעוד רשמי, עיינו ב-Substrate Developer Hub: Ink!.







