ביקורת חוזים חכמים: היכן הלוגיקה נשברת לפני הפריצה הראשונה
חוזה חכם לא ניתן לתקן בשקט: לאחר הפרסום הלוגיקה מבוצעת בדיוק כפי שנכתבה, ושגיאה בה הופכת להזמנה פתוחה. ביקורת חוזים חכמים מחפשת לא שגיאות כתיב, אלא נקודות כשל שבהן קריאה אחת מוציאה מהפרוטוקול יותר ממה שהושקע בו.
אנחנו בוחנים לא רק את הקוד, אלא גם את הקישורים לאורקלים של מחירים, לבריכות נזילות ולארנקים של משתמשים.
הנקודה הטיפוסית הראשונה — זכות משיכת כספים של תפקיד אחד. אם כתובת יחידה יכולה לקחת את כל הנזילות ללא השהיה, מגבלות וחתימה שנייה, מחיר הטעות במפתחות שווה למחיר כל הבריכה. זכויות כאלה אנחנו מפצלים לתפקידים, מוסיפים תור לביצוע ותקרה למשיכה חד-פעמית.
השנייה — סדר החישובים. כאשר היתרה מתעדכנת לאחר קריאה חיצונית, החוזה מספיק להגיב לפנייה חוזרת עם המצב הקודם ולהוציא כספים פעמיים. אותו סוג מוביל לעיגול לטובת הקורא — בזרם עסקאות זהו סיכון מתמשך להוצאת כספים.
השלישית — קריאות חיצוניות ללא בדיקת התוצאה: סירוב שהוחזר, מחיר מיושן, תשובה ריקה עוברים כהצלחה, והפרוטוקול רושם עסקה על נתונים שגויים. הגנת DeFi מפני פריצה מתחילה בבדיקת כל תשובה חיצונית והגבלתה בזמן.
פרימיטיבים בסיסיים אנחנו לוקחים מספריות מוכחות — OpenZeppelin — ולא כותבים אריתמטיקה משלנו במקום שבו היא כבר עברה בדיקה ציבורית. בהמשך נפרט כיצד פגיעויות חוזים חכמים אלו נסגרות לפני שחרור ומה נשאר בדוח.
מה משתנה לאחר הבדיקה: מחלקות סירוב שנסגרו ומהירות התיקונים
לאחר הבדיקה רשימת מחלקות הפגיעויות הפתוחות מצטמצמת לאפס ברמת הקריטיות והגבוהה: כניסה חוזרת דרך קריאות חיצוניות, עקיפת בקרת גישה למתודות מורשות, מניפולציה של מחיר האורקל בבריכה דקה, שגיאות עיגול בצבירת עמלות, תלות התוצאה בסדר העסקאות. כל מחלקה לא רק נקראת בשם — היא מאושרת בתרחיש ניצול ונסגרת בתיקון במתודה ספציפית.
ההשפעה השנייה — כיסוי. מנתח סטטי כמו Slither לוכד פגמים פורמליים, אך משמעות מכרעת יש לאינווריאנטים שמורצים בפאזינג על אלפי רצפי קריאות: שלמות סכום היתרות, מונוטוניות האינדקס, אי-נגישות משיכה מעל לחלק. שיעור הנתיבים המכוסים בבדיקות כאלה הופך לכמות מדידה, ולא להצהרה בדוח.
מהירות הוצאת התיקונים משתנה באופן איכותי: תרחיש התקיפה שנמצא הופך לבדיקת רגרסיה, והגרסה המתוקנת נבדקת בהרצה חוזרת של כל המערכת, ולא בסקירה ידנית של השורות ששונו. הדרך מהממצא לגרסה מתוקנת מסתכמת במחזור תיקונים אחד במקום סדרת איטרציות של «מצאנו — כתבנו מחדש — מצאנו שוב».
צפיות השחרורים נשענת על כלל נוקשה: פריסה אינה עוברת כאשר קיים ממצא קריטי פתוח. רשימת הבדיקות מוטמעת בצינור הבנייה, הדוח מתעד את הסטטוס של כל מחלקת פגיעויות, וההחלטה על שחרור מתקבלת לפי סגירת הסיכונים, ולא לפי תחושת המוכנות של הצוות.
ביקורת חוזים חכמים: ניתוח ידני ובדיקות מכונה
ביקורת חוזים חכמים אינה מצטמצמת לכלי אחד. ניתוח סטטי של חוזים עובר במהירות על כל הקוד ולוכד פגמים טיפוסיים — קריאות חיצוניות לפני שינוי המצב, משיכת כספים לא מוגנת, גלישות.
אך המנתח אינו מבין את כוונת הפרוטוקול: הוא אינו מבחין בין האצלת זכויות מכוונת לבין שגיאת גישה, ולכן על כל פגם אמיתי יש עשרות התראות שווא של מנתחים. ניתוח ידני של הקוד סוגר את הפער הזה — נבדקים הכלכלה, סדר הקריאות ומצבי הקצה לפי תרחישים.
פורמטי הבדיקה נבדלים בעומק ובסוג השגיאה שהם בכלל מסוגלים לראות:
| סוג הבדיקה | מתי מתאים | מגבלות |
|---|---|---|
| ניתוח ידני של הקוד | לוגיקת הפרוטוקול, הכלכלה, זכויות תפקידים, חיבורים לחוזים חיצוניים | דורש זמן וכישורים, הכיסוי תלוי בנתיבים שנבחרו |
| ניתוח סטטי של חוזים | מעבר ראשון על כל בסיס הקוד, חיפוש פגיעויות טיפוסיות, בדיקה בצינור הבנייה | הרבה התראות שווא, אינו רואה שגיאות לוגיות |
| אימות פורמלי | אינווריאנטים קריטיים: שלמות יתרות, מגבלות הנפקה, תנאי פירוק | נדרש מפרט פורמלי; ישים לליבה, לא לכל המערכת |
| בדיקה חוזרת לאחר תיקונים | כל תיקון שנוגע באחסון המצב או בקריאות חיצוניות | בודק את הקטעים ששונו, דורש הערכת השפעה על שאר המערכת |
בפועל הגישות הולכות יחד: מעבר מכונה על כל המאגר, ניתוח ידני של נתיבים קריטיים, אימות פורמלי של הליבה ובדיקה חוזרת לאחר כל תיקון. כך נסגרים גם שגיאות טיפוסיות וגם פגמים לוגיים שהכלי לא יראה באופן עקרוני.
כיצד מתבצעת ההטמעה: מניתוח הקוד ועד מסירת הדוח
הבדיקה מתבצעת בשלבים עוקבים: תחילה מתעדים מה החוזה מחויב לעשות, לאחר מכן — כיצד הוא עלול לעשות את הלא-נכון. בלי הצעדים הראשונים הביקורת מצטמצמת להרצה של מערכת כללים מוכנה, וחלק מנתיבי התקיפה נשאר מחוץ לניתוח.
- איסוף דרישות וגבולות. מדייקים את הלוגיקה, התפקידים, מקומות אחסון הכספים והקריאות החיצוניות; רושמים את האינווריאנטים שאסור להפר בשום תנאי.
- תרשים החוזה והתפקידים. מפת הקריאות, הזכויות והתלויות בין המודולים מראה היכן משתתף אחד יכול לפגוע בכספים של אחרים.
- ניתוח שורה-שורה. עוברים לפי התרשים דרך הקוד: אריתמטיקה ועיגולים, בדיקות גישה, סדר עדכון המצב, עבודה עם קריאות חיצוניות.
- הרצת תרחישי תקיפה. הטבעה חוזרת של קריאות, מניפולציה של מחיר, עקיפת עסקאות, משיכה מעל ליתרה — כל השערה מאושרת בבדיקה, ולא בהנחה.
- תיקון. יחד עם הצוות שלכם מבצעים תיקונים או מוסרים טלאים ממוקדים, ומסמנים היכן משתנה הלוגיקה, ולא רק ההגנה.
- בדיקת בקרה. מריצים מחדש את התרחישים ומוודאים שהטלאי לא פתח נתיב חדש ולא שבר את האינווריאנטים מהסעיף הראשון.
- מסירת הדוח. ממצאים עם רמת סיכון, נתיב שחזור וסטטוס תיקון; כאשר הלוגיקה משתנה — בדיקה חוזרת לאחר העלאה לרשת.
כל שלב משאיר עקבות: ניתן לראות מה נבדק, מה נותר ועל מה מבוססת המסקנה.
מה נשאר בפרויקט: קונפיגורציות, תרשים ותקנות
הביקורת מסתיימת לא בפסק דין «לא נמצאו פגיעויות», אלא בסט ארטיפקטים שאיתו הצוות ממשיך לעבוד בלעדינו: להלן — מה נשאר במאגר לאחר מסירת הבדיקה.
- דוח הבדיקה — עבור כל הערה: מחלקת סיכון, נתיב ביצוע, הפניה לפונקציה ותרחיש שחזור מינימלי. אין ניסוחים כמו «מומלץ לבדוק»: או קריאה קונקרטית, או שהסעיף לא נכנס לדוח.
- ארטיפקטים של הבדיקה — קונפיגורציות של ניתוח סטטי, תרחישי פאזינג, בדיקות אינווריאנטיות וחתכי כיסוי. הסט מופעל מחדש בפקודה אחת, ולכן התוצאה ניתנת לשחזור.
- תרשימי גישה — מפת תפקידים: מי מנפיק נכסים, משנה פרמטרים, מקפיא פעולות ומעדכן לוגיקה; תפקידים עם השהיית ביצוע ומועמדים לחתימה מרובה מסומנים בנפרד.
- מדיניות שינויים — אילו תיקונים דורשים בדיקה חוזרת, ואילו עוברים בהליך מקוצר; כללים לעדכון לוגיקה דרך פרוקסי ואיסור על שינוי סדר השדות באחסון.
- תקנון בדיקות חוזרות — טריגרים: תיקון חישובים, שינוי פרמטרים כלכליים, הרחבת זכויות מנהל, חיבור מקור נתונים חיצוני.
- תיעוד החוזה — אינווריאנטים, מודל אירועים לניטור, רשימת קריאות חיצוניות והנחות שעליהן נשענת הלוגיקה.
- יומן סיכונים מקובלים — הערות שהושארו במכוון ללא תיקון, עם נימוק והערכת השלכות: צוות חדש לא יצטרך לברר זאת מחדש.
הסט מסיר את התלות בקבלן: את הבדיקה הבאה ניתן לבצע בכוחות עצמכם או להעביר לצוות אחר — נקודת הכניסה אחת.
ניתוח מקרה: לפני ואחרי סגירת פגיעות קריטית
מה היה לפני התיקון
מקרה הבדיקה של חוזה החל בשתי ביקורות אצל קבלנים קודמים: החוזה נבנה, המנתחים הסטטיים נתנו דוח נקי. בלוגיקת משיכת הכספים נותרה קריאה חוזרת — החוזה החיצוני הספיק להחזיר שליטה לפני עדכון היתרה הפנימית.
המחלקה מתוארת ב-SWC Registry כאינטראקציה לפני שינוי המצב — אף סורק לא סימן אותה כאן, משום שהפגיעות התגלתה רק בחיבור של קריאות, ולא בתוך פונקציה אחת.
מה נמצא ומה שינו
המהנדסים עברו על זרם הקריאות מהפקדת כספים ועד משיכה ותמצתו לתרשים של שינוי יתרות — עליו נראה החלון בין החיוב לרישום. תרחיש התקרית עם הנזילות שוחזר על עותק מקומי של הרשת: סדרת קריאות שאבה מהבריכה יותר ממה שהופקד בה, ועשתה זאת ללא שגיאה אחת בלוגים.
התיקון צומצם לסדר «בדיקה — רישום — קריאה חיצונית», נוספה הגנה מפני כניסה חוזרת ובדיקת רגרסיה שנופלת בחזרה לסדר הפעולות הישן.
| מדד | לפני | אחרי |
|---|---|---|
| תגובה לאנומליה בבריכה | שעות | דקות |
| שיעור נתיבי משיכת הכספים תחת בדיקות | 40% | 95% |
| זיהוי מחלקת «קריאה חוזרת» | לא זוהתה | נסגרה בבדיקה |
לאחר סגירת הפגיעות הקריטית הבדיקה החוזרת לא מצאה נתיבי זליגה חדשים, והניטור של הבריכה הועבר להתראות סף לפי נפח היתרות. חזרה לגרסה קודמת של החוזה נותרה זמינה — התיקונים בוצעו כך שמצב הבריכה לא דרש הגירה.
במה שונה בדיקה לפני הפעלה מניתוח לאחר תקרית?
בדיקה לפני הפעלה היא עבודה עם קוד המקור לפני שהכסף נכנס לחוזה. המהנדסים עוברים על כל ענפי הביצוע: זכויות מנהל, קריאות חיצוניות, סדר עדכון המצב, תלויות במקורות נתונים חיצוניים. בנפרד מדמים תרחישים כלכליים — מניפולציה של שער, משיכת נזילות, האצת שווי הטוקן.
ניתוח לאחר תקרית פותר משימה אחרת: לעצור את ההפסדים ולהבין את הווקטור. הסדר הפוך — תחילה עקבות העסקאות ברשת, לאחר מכן שחזור רצף הקריאות, ורק אז הסיבה בקוד. אם קוד המקור אינו זמין או שהקוד הפרוס שונה ממנו, הניתוח נעשה לפי בייט-קוד.
ההבדל בין הגישות הוא במטרות, ולא בכלים. לפני הפעלה נדרשת שלמות: לכסות את כל נתיבי הביצוע, לתאר מחלקות סיכון ותנאים למימושן. לאחר תקרית נדרשת מהירות: שניים-שלושה צמתים שדרכם עברה משיכת הכספים, צעדים דחופים — השהיה, הגירה, עדכון החוזה — ורק אז ניתוח מלא של מה שקרה.
בדיקה חוזרת הכרחית בשני המצבים. טלאי לעתים סוגר וקטור אחד ופותח שכן, ולכן הקוד המתוקן עובר מחדש את אותם תרחישים, ולא נסקר בעין. לאחר תקרית, הכללים שנמצאו מועברים לבדיקות מניעתיות של השחרורים הבאים.
ספקות טכניים נפוצים לפני תחילת העבודה
ספקות לפני ביקורת לעתים רחוקות נוגעים למתודולוגיה — לעתים קרובות יותר שואלים על גבולות העבודה: מה באמת נבדק בקוד שכבר הועלה, היכן נגמרת האוטומציה ומתחיל הניתוח הידני, מי אחראי על הממצאים לאחר המסירה. להלן — תשובות למה שנשמע בניתוח הראשון.
החוזה כבר פרוס — מאוחר מדי לבדוק?
לא, אם כי התיקונים יקרים יותר. משווים את הקוד ברשת לקוד המקור, בודקים אם הלוגיקה מתעדכנת דרך פרוקסי ומי מחזיק בזכויות השינוי. אם החור נסגר בעדכון — מכינים טלאי, אם לא — מחשבים העברת מצב.
האם מנתחים אוטומטיים מספיקים?
לא. הם לוכדים שגיאות תבניתיות: עקיפת בדיקות גישה, גלישות, משתנים לא מאותחלים. את לוגיקת הפרוטוקול כך לא רואים — אותה מנתחים ידנית ומריצים בתרחישים על עותק הרשת.
האם בודקים גם את הלוגיקה הכלכלית?
כן, במסלול נפרד: מניפולציות בשער, סדר פירוקים, רגע זיכוי התגמולים, תלות במקור מחיר חיצוני. קוד תקין עם כלכלה שגויה מאבד כספים באותה מידה של ביטחון.
מה קורה לאחר תיקונים לפי הדוח שלכם?
בדיקה חוזרת של הקטעים ששונו, ולא של כל הקוד מחדש: מאשרים שאכן נסגרו הנתיבים שנמצאו ולא הופיעו חדשים. סט בדיקות הרגרסיה נשאר בידי הצוות.
מה עם האחריות לאחר המסירה?
מוסרים דוח עם רמות סיכון, בדיקות ותרשימי קריאות; איננו מחזיקים במפתחות ואיננו מנהלים את הפרוטוקול. אנחנו אחראים על המתודולוגיה ועל שחזור המסקנות, ולכן בדיקות חוזרות לאחר כל עדכון מהותי מתוכננות מראש.
בואו נדון במשימה: מה להבהיר לפני תחילת הבדיקה
כדי לחזור עם הערכת לוחות זמנים ותוכנית עבודה, ולא עם שאלות הבהרה, מספיקים לנו כמה נתוני פתיחה. ככל שגבולות המערכת ומודל התפקידים מתוארים מדויק יותר, כך יש פחות הנחות באומדן וגדל הסיכוי לעמוד בתאריך ההפעלה.
מה עוזר לדון במשימה באופן ענייני:
- גבולות הבדיקה: אילו חוזים נמצאים בהיקף, ואילו קריאות חיצוניות — אורקלים, גשרים, בריכות נזילות — נחשבות מהימנות ואינן נבחנות.
- תרשים תפקידים והרשאות: למי יש פונקציות מנהל, האם קיימת חתימה מרובה והשהיה לפעולות קריטיות כמו משיכת כספים.
- היסטוריית שינויים וקוד המקור: כיצד להתאים את המאגר לחוזה הפרוס ברשת, כך שהלוגיקה תתאים לבנייה.
- תקריות מוכרות והנחות: מה כבר מצאתם בעצמכם, מה הושאר במכוון כפי שהוא, ואילו מקומות הצוות מחשיב כמסוכנים.
- דרישות רגולטורים ופלטפורמות: פורמט החוות דעת שיקבלו שותפים או זירת מסחר, והסעיפים הנדרשים בדוח.
- לוחות זמנים להפעלה או לשחרור הבא: מתאריך תלוי סדר העבודה — תחילה נתיבים קריטיים, לאחר מכן שאר הלוגיקה.
- כלכלת הפרוטוקול: כיצד מחושבים חלקים, עמלות ופירוקים — פערים בנוסחאות הם לרוב מה שפותח את הדרך לאובדן כספים.
לאחר מכן תיאום ההיקף מתבצע בשיחה אחת: מתעדים מה נכנס לבדיקה, מה נשאר מחוץ להיקף, ובאיזה סדר מוסרים את התוצאות — לפי נתיבים קריטיים מוקדם יותר מאשר לפי ההיקף המשני.







