ברכות לסיום קורס סולידיטי החלק הראשון! והיכונו לחלק השני של הקורס ובו נתרכז בעיקר בחוזה החכם עצמו, כתיבת החוזה בסיסה לוקלאית, מה זה ABI, שימוש בחוזה בסביבות שונות ועוד..
אז יאללה מתחילים! בתוך התחלה, פותחים רמיקס (כרגע) וכותבים חוזה חכם ראשון, חוזה פשוט, החוזה שלנו יעסוק בהעברת תשלום כתרומה ונקרא לחוזה שלנו FundMe . קיימים מדריכים דומים לfundme באינטרנט כך שתוכלו גם לראות דוגמאות דומות במידה ותרצו – שוב זה חוזה בסיסי ומוכר בכוונה על מנת להקל על תהליך הלמידה בשלב זה. וכמובן על הדרך נלמד המון דברים חשובים!
מה יכלול החוזה החכם שכתוב
החוזה יכיל כמה פונקציות בסיסיות:
- יוזר יוכל לתרום כסף לחוזה, לשם כך נצטרך פונקציה fund שככל הנראה תהיה payable
- אפשרות משיכה של הכסף הצבור בחוזה (על ידי owner בלבד)
נתחיל עם הפונקציה ראשונה והמרכזית:
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.9; contract FundMe { function fund() public payable { require(msg.value >= 1e18, "the minimum to fund is 1 eth"); } }
בואו נעצור פה ונלמד משהו חדש ומעניין: require
require הוא למעשה תנאי, אבל לא if רגיל שאנחנו מכירים, require יש תכונות מיוחדות שהוגדרו בשפה של סולידיטי, למעשה במידה והתנאי בrequire לא עבר, אז מתבצע revert של הפקודות שרצו בפונקציה זו, וגם גז יוחזר, לצורך הדוגמה אם תרצו לשמור את היוזר שהעביר תרומה במערך של כתובות, ותרשמו זאת אפילו לפני require עדיין פעולה זו תוחזר ולא תשמר שום כתובת. להלן הדוגמה בקוד שתעזור לכם להבין על מה דיברתי כרגע:
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.9; contract FundMe { mapping(address => uint256) public funders; function fund() public payable { funders[msg.sender] += msg.value; require(msg.value >= 1e18, "the minimum to fund is 1 eth"); } }
עוד משהו חדש הוא ההגדרה של mapping(address => uint256) למעשה mapping הוא בדומה לjavascript. וכמו שאנחנו יודעים סולידיטי היא שפה שמוגדרת כ static type אז חשוב להגדיר מה יהיה ה key \ value ובשביל לשמור כתובות של תורמים ואת הסכום שתרמו , נגדיר map כך שכתובת תקבל ערך מספרי. וכפי שאפשר לראות אנו שומרים זאת בפונקציה של fund, וכפי שאנחנו למדנו, require עושה ריברט ולכן המידע לא ישמר במערך מסוג map. השאלה שלרוב שואלים, "מה אם הגז ששולם על פעולות אלו שחזרו, האם הגז חוזר גם כן? בגדול התשובה היא כן, הגז חוזר, אבל נעבור על זה בצורה יותר מפורטת בהמשך (כרגע לא נתרכז בנושא של גז ואופטימזציה שלו).
נמשיך ונסיים את החוזה שלנו עם פונקציה נוספת, פונקציה שתאפשר לנו למשוך את הכסף הצבור בחוזה לארנק שנבחר\ או לארנק של בעל החוזה – לכל חוזה יש owner.
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.9; contract FundMe { mapping(address => uint256) public funders; function fund() public payable { funders[msg.sender] += msg.value; require(msg.value >= 1e18, "the minimum to fund is 1 eth"); } function withdraw() public { payable(msg.sender).transfer(address(this).balance); } }
הקוד בדוגמה כאן אינו יעזור לכם כלל. אומנם הוא יעבור אבל הבעיה היא שכל מי שיקרא לפונקציה הזו ויצליח למשוך את הכסף מהחוזה שלכם. ולכן בחרתי להציג זאת, שתראו קצת דוגמאות שלא עושים בטח אם הם קריטיות כמו פונקציית withdraw. מה שנרצה לעשות זה לבדוק שאכן מבקש המשיכה הוא אכן ביוצר של החוזה.
הנה מהלך זריז ופשוט להגדיר כתובת owner של החוזה, נשתמש בconstructor:
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.9; contract FundMe { mapping(address => uint256) public funders; address public owner; constructor() { owner = msg.sender; } function fund() public payable { funders[msg.sender] += msg.value; require(msg.value >= 1e18, "the minimum to fund is 1 eth"); } function withdraw() public { require(msg.sender == owner, "you are not the owner"); payable(msg.sender).transfer(address(this).balance); } }
כידוע לנו כמתכנתים, constructor ירוץ רק ביצירה הראשונית במחלקות וגם בסולידיטי באופן דומה. ולכן owner יהיה שווה לכתובת של מי שהעלה את החוזה. ואז נשתמש שוב ב require שיבדוק ויעצור את התהליך במידה ומישהו אחר ינסה להריץ את withdraw . שימו לב שנשתמש ב == לבדוק שוויון בסולידיטי.
לסיכום – קורס סולידיטי – כתיבת חוזה חכם
ברגע זה כתבתם את החוזה החכם הראשון שלכם! כל הכבוד! זוהי רק ההתחלה ונמשיך ונפתח על החוזה הזה עוד דברים על מנת לתת לכם יותר פרקטיקה בכתיבה של דברים שלמדנו בפרק הראשון, וכן נלמד עוד דברים תוך כדי הכתיבה של החוזה שלנו, כרגע העלאת החוזה החכם נבדק בסביבה של remix בהמשך נעלה את החוזה לסביבות נוספות, דרך רמיקס וגם לוקאלית. העזרו בסבלנות
