פיתוח השכרת NFT (ERC-4907)
גילדת גיימינג עם 5000 גיבורי NFT על Polygon נתקלה בבעיה: איך להשכיר אותם למצטרפים חדשים מבלי להעביר בעלות? לפני EIP-4907, השכרה יושמה באמצעות פתרונות עוקפים — העברת טוקן לנאמנות (escrow), הסכמים מחוץ לשרשרת המבוססים על אמון, או מיפוי תפקידים מותאם אישית ללא תקן אחיד. כל פרוטוקול שרצה להשתמש ב-NFT של מישהו אחר (משחק, מטאוורס, הלוואות) נאלץ לכתוב אינטגרציה לכל פרויקט בנפרד. הצוות שלנו — 10+ שנות ניסיון בפיתוח בלוקצ'יין, 40+ פרויקטים מוצלחים — כבר יישם עשרות פתרונות השכרה המבוססים על ERC-4907: מחוזים פשוטים ועד מרקטפלייס מלאים עם הזמנות מחוץ לשרשרת.
EIP-4907 פותר זאת בצורה נקייה: מוסיף כתובת שנייה — user — עם זכויות שימוש זמניות, תוך השארת הבעלות ללא שינוי. חיסכון בזמן אינטגרציה — עד 70% בהשוואה לפתרונות מותאמים אישית. אנו מבטיחים אבטחה ותאימות לכל הרשתות הפופולריות (Ethereum, Polygon, Arbitrum, Base). אינטגרציה עם ERC-4907 מהירה פי 3 מכתיבת חוזה השכרה מותאם אישית, והגישה ללא נאמנות חוסכת עד 30% גז לכל פעולה.
כיצד ERC-4907 עובד
התקן מרחיב את ERC-721 עם שתי פונקציות ואירוע אחד:
interface IERC4907 {
event UpdateUser(uint256 indexed tokenId, address indexed user, uint64 expires);
function setUser(uint256 tokenId, address user, uint64 expires) external;
function userOf(uint256 tokenId) external view returns (address);
function userExpires(uint256 tokenId) external view returns (uint256);
}נקודה מרכזית: interface IERC4907 { event UpdateUser(uint256 indexed tokenId, address indexed user, uint64 expires); function setUser(uint256 tokenId, address user, uint64 expires) external; function userOf(uint256 tokenId) external view returns (address); function userExpires(uint256 tokenId) external view returns (uint256); } מאופס אוטומטית ל-user לאחר address(0). ללא cron-job, ללא keeper — רק בדיקה ב-expires:
function userOf(uint256 tokenId) public view virtual returns (address) {
if (uint256(_users[tokenId].expires) >= block.timestamp) {
return _users[tokenId].user;
}
return address(0);
}userOf() שומר על שליטה מלאה: יכול להעביר את הטוקן, לקבל תמלוגים, להגדיר function userOf(uint256 tokenId) public view virtual returns (address) { if (uint256(_users[tokenId].expires) >= block.timestamp) { return _users[tokenId].user; } return address(0); } חדש. בעת העברת טוקן, owner ו-user מאופסים אוטומטית — הגנה מפני שימור זכויות על ידי השוכר לאחר שינוי בעלות.
איזו ארכיטקטורה לבחור: ללא נאמנות או עם נאמנות?
ERC-4907 עצמו הוא רק תקן ברמת הטוקן. מערכת השכרה מלאה דורשת חוזה השכרה נוסף מעליו.
השוואת גישות
| מאפיין | ללא נאמנות | עם נאמנות |
|---|---|---|
| מיקום הטוקן | ארנק הבעלים | נעול בחוזה |
| סיכון לאובדן טוקן | נמוך (ללא סיכון משמורת) | גבוה אם החוזה פגום |
| גז לכל רישום | 0 (חתימה מחוץ לשרשרת) | ~50k גז (העברה) |
| מקרה שימוש | משחקים, מטאוורסים, הלוואות | הלוואות עם בטחון, מכירות פומביות |
ללא נאמנות (מומלץ): הבעלים מאשר את חוזה ההשכרה באמצעות user, השוכר משלם, החוזה קורא ל-expires בשם הבעלים. הטוקן נשאר אצל הבעלים לאורך כל תקופת ההשכרה. גישה ללא נאמנות חוסכת עד 30% גז לכל השכרה על ידי הימנעות מהעברות מיותרות.
השוואת עלויות גז
| פעולה | גז (ללא נאמנות) | גז (עם נאמנות) |
|---|---|---|
| רישום | 0 (מחוץ לשרשרת) | ~50,000 |
| השכרה (יום אחד) | ~100,000 | ~150,000 |
| הארכה | ~40,000 | ~70,000 |
| החזרה | 0 | ~30,000 |
חיסכון בגז עם גישה ללא נאמנות: עד 0.0005 ETH לכל השכרה על Ethereum.
מבנה הזמנת השכרה
struct RentalOrder {
address tokenContract;
uint256 tokenId;
address lender;
uint256 pricePerDay; // в wei
uint64 minDuration; // в секундах
uint64 maxDuration;
uint64 deadline; // до когда ордер валиден
bytes signature; // EIP-712 подпись лендера
}ספר הזמנות מחוץ לשרשרת (כמו פרוטוקול 0x) + סילוק על השרשרת. המלווה חותם על ההזמנה מחוץ לשרשרת — ללא עלות גז לרישום. השוכר קורא ל-approve() — עסקה אחת: תשלום + setUser().
חידוש אוטומטי וסיום מוקדם
ERC-4907 אינו מספק סיום מוקדם על ידי המלווה — struct RentalOrder { address tokenContract; uint256 tokenId; address lender; uint256 pricePerDay; // в wei uint64 minDuration; // в секундах uint64 maxDuration; uint64 deadline; // до когда ордер валиден bytes signature; // EIP-712 подпись лендера } אינו ניתן לשינוי לאחר rent(order, duration). עבור השכרה מבוססת בטחון (הגנה מפני נזק לנכס במשחקים), נדרשת לוגיקה נוספת: הפקדת שוכר + יכולת מלווה לקנוס עם הוכחה על השרשרת להפרה.
אינטגרציה למשחקים ופרוטוקולים
פרוטוקולים צריכים להחליף setUser() ב-expires:
// Было: require(IERC721(nft).ownerOf(tokenId) == msg.sender, "Not owner");
// Стало: address user = IERC4907(nft).userOf(tokenId);
require(user == msg.sender, "Not authorized user");לתאימות לאחור עם חוזים שאינם תומכים ב-ERC-4907: חוזה עטיפה שעוטף ERC-721 סטנדרטי ל-ERC-4907. הבעלים מפקיד את הטוקן המקורי ומקבל גרסה עטופה עם פונקציונליות השכרה.
טעויות נפוצות
- שכחת לבדוק
setUser()ב-ownerOf()— השתמש בבדיקה המובנית של התקן. - אי איפוס
userOf()בעת העברה — התקן עושה זאת אוטומטית. - שימוש ב-
// Было: require(IERC721(nft).ownerOf(tokenId) == msg.sender, "Not owner"); // Стало: address user = IERC4907(nft).userOf(tokenId); require(user == msg.sender, "Not authorized user");במקוםexpiresבלוגיקת השימוש — איבוד שוכרים. - אי חתימת הזמנות עם EIP-712 — הרישום ידרוש גז.
- אי הגנה על
userOf()מפני קריאות זדוניות ישירות — השתמש במודיפייר onlyOwner.
מה כלול בפיתוח?
- חוזה ERC-4907 (אם הקולקציה חדשה) או עטיפה לקיימת
- חוזה מרקטפלייס השכרה: הזמנות מחוץ לשרשרת עם חתימות EIP-712, סילוק על השרשרת
- לוגיקת תמחור: מחיר קבוע ליום, מכירה הולנדית למחיר יורד לאורך זמן
- פרונטאנד: רישום, חיפוש טוקנים זמינים, השכרה בלחיצה אחת
- אינטגרציה עם פרוטוקול הצרכן: החלפת
userב-ownerOf()
כיצד אנו מפתחים השכרת NFT
- ניתוח: הגדרת דרישות לוגיקת השכרה, משכי זמן, תמחור.
- עיצוב: ארכיטקטורת חוזה חכם, בחירה בין ללא נאמנות לעם נאמנות.
- יישום: קוד Solidity באמצעות Foundry, בדיקות (יחידה + fuzzing עם Echidna).
- ביקורת: בדיקות reentrancy, אופטימיזציית גז, אימות פורמלי של פונקציות מפתח.
- פריסה: הגדרת חוזים לרשת הנבחרת (Ethereum, Polygon, Arbitrum), אימות קוד על Etherscan.
- אינטגרציה: חיבור פרונטאנד, כתיבת תיעוד למפתחים.
הערכות לוחות זמנים
- רק חוזה ERC-4907 + השכרה בסיסית: מיומיים.
- עם ספר הזמנות מחוץ לשרשרת, פרונטאנד ואינטגרציית חוזה משחק: 4-5 ימים.
העלות מחושבת באופן אישי לפי מורכבות והיקף. חיסכון בגז עד 30% מפחית עלויות תפעול — בעומס טיפוסי, כ-$0.05 לעסקה. צור קשר לייעוץ על הפרויקט שלך. הזמן פיתוח השכרת NFT היום.







