פרוטוקול ה-DeFi שלך מכניס מיליוני דולרים בעמלות מדי חודש, אבל אתה לא יודע איך לחלק אותם בצורה הוגנת בין 50,000 מחזיקי טוקנים בלי לשלם יותר מדי על גז ולסכן התקפות flash loan. טעות נפוצה היא שימוש בלולאת for נאיבית לחלוקה, שעבור מספר גדול של מחזיקים מובילה לעלויות גז במאות ETH. אנחנו משתמשים ב-Merkle tree או במדד rewardPerToken, ומפחיתים עלויות פי 5–10. הצוות שלנו יישם מעל 20 פרויקטים, כולל פרוטוקולים עם TVL עד $500M. אנחנו מבטיחים ביקורת אבטחה ותמיכה שוטפת. מאמר זה בוחן מודלים מרכזיים של חלוקת הכנסות ושיטות הגנה.
כיצד פועלת מערכת חלוקת הכנסות למחזיקי טוקנים?
מערכת חלוקת הכנסות בין מחזיקי טוקנים דורשת התחשבות במספר המחזיקים, תדירות התשלומים והאבטחה. נבחן שלוש גישות פופולריות.
כיצד לבחור מודל חלוקת הכנסות?
בחירת המודל תלויה במספר המחזיקים ובתדירות התשלומים.
סטרימינג רציף (Superfluid/Sablier)
ההכנסות "זורמות" למחזיקים ברציפות ביחס ליתרה. תיאורטית אידיאלי—מעשית מורכב: כל העברת טוקן דורשת חישוב מחדש של הזרמים. ב-Ethereum זה יקר עבור מספר גדול של מחזיקים. מתאים למספר קטן של משתתפים ולתדירות תשלומים גבוהה.
Snapshot + חלוקת Merkle
המודל הנפוץ ביותר. פעם אחת בתקופה (שבוע/חודש) נלקח snapshot של היתרות, כל חלק מחושב, ונבנה עץ Merkle. המחזיקים עצמם תובעים את חלקם על ידי מתן הוכחת Merkle. לפי תיעוד OpenZeppelin, עץ Merkle מאפשר אימות מבלי לחשוף את כל הנתונים, מה שחיוני לפרטיות.
contract RevenueDistributor { IERC20 public immutable rewardToken; bytes32 public merkleRoot; uint256 public distributionId; mapping(uint256 => mapping(address => bool)) public claimed; function setDistribution(bytes32 _root) external onlyOwner { distributionId++; merkleRoot = _root; emit DistributionSet(distributionId, _root); } function claim( uint256 amount, bytes32[] calldata proof ) external { require(!claimed[distributionId][msg.sender], "Already claimed"); bytes32 leaf = keccak256(abi.encodePacked(msg.sender, amount)); require(MerkleProof.verify(proof, merkleRoot, leaf), "Invalid proof"); claimed[distributionId][msg.sender] = true; rewardToken.transfer(msg.sender, amount); emit Claimed(distributionId, msg.sender, amount); } } ניתן להרחבה לכל מספר מחזיקים, הגז משולם על ידי הנמען. דורש תשתית off-chain ליצירת snapshot ועץ Merkle. חלוקת Merkle זולה פי 5 בגז מאשר סטרימינג רציף עבור 10,000 מחזיקים. עלות הגז לתביעה עם חלוקת Merkle היא כ-0.01 ETH ($20 בשערים הנוכחיים).
טוקן עם דיבידנדים (Synthetix Rewards)
מודל MasterChef / Synthetix Rewards: חוזה מאחסן contract RevenueDistributor { IERC20 public immutable rewardToken; bytes32 public merkleRoot; uint256 public distributionId; mapping(uint256 => mapping(address => bool)) public claimed; function setDistribution(bytes32 _root) external onlyOwner { distributionId++; merkleRoot = _root; emit DistributionSet(distributionId, _root); } function claim( uint256 amount, bytes32[] calldata proof ) external { require(!claimed[distributionId][msg.sender], "Already claimed"); bytes32 leaf = keccak256(abi.encodePacked(msg.sender, amount)); require(MerkleProof.verify(proof, merkleRoot, leaf), "Invalid proof"); claimed[distributionId][msg.sender] = true; rewardToken.transfer(msg.sender, amount); emit Claimed(distributionId, msg.sender, amount); } } . עם כל זרימת הכנסה חדשה, המדד מתעדכן. בעת תביעה, המשתמש מקבל את ההפרש בין המדד הנוכחי לזה שבמועד התביעה האחרונה.
uint256 public rewardPerTokenStored; mapping(address => uint256) public userRewardPerTokenPaid; mapping(address => uint256) public rewards; function rewardPerToken() public view returns (uint256) { if (totalStaked == 0) return rewardPerTokenStored; return rewardPerTokenStored + ( (rewardRate * (block.timestamp - lastUpdateTime) * 1e18) / totalStaked ); } function earned(address account) public view returns (uint256) { return ( (balanceOf(account) * (rewardPerToken() - userRewardPerTokenPaid[account])) / 1e18 ) + rewards[account]; } זוהי פעולה O(1) לכל משתמש—אין צורך ב-snapshot של כל המחזיקים. אידיאלי לחוזי staking. Synthetix rewards זול פי 10 לתביעה מאשר חלוקת Merkle, עם עלות גז נמוכה עד 0.001 ETH ($2).
השוואת מודלים
| פרמטר | חלוקת Merkle | Synthetix Rewards | סטרימינג רציף |
|---|---|---|---|
| מספר מחזיקים | כל מספר | עד 10,000 | עד 1,000 |
| תדירות תשלומים | מחזורית | עם קבלת הכנסות | רציפה |
| עלות גז לתביעה | 0.01 ETH (משתמש) | 0.001 ETH (חוזה) | גבוהה (חוזה) |
| צורך ב-off-chain | כן | לא | לא |
| הגנה מפני flash loan | נפרדת | מובנית (TWB) | מובנית (TWB) |
מדוע הגנה מפני flash loan היא קריטית?
תוקף לוקח flash loan לכמות עצומה של טוקנים, ה-snapshot נופל באותו בלוק, והם תובעים חלק גדול באופן לא פרופורציונלי. ללא הגנה, המערכת יכולה לאבד עד 100% מההכנסות המחולקות בבלוק אחד. הניסיון שלנו מראה שיתרה משוקללת בזמן מפחיתה את שטח התקיפה ב-99%.
פתרון 1: יתרה משוקללת בזמן. ה-snapshot מחשב לא את היתרה הנוכחית אלא את הממוצע המשוקלל בזמן על פני התקופה. זה הופך התקפות flash loan ללא יעילות—הממוצע יהיה קרוב לאפס. חיסכון בגז יכול להגיע ל-80% באמצעות snapshot off-chain.
פתרון 2: תקופת החזקה מינימלית. רק כתובות שמחזיקות טוקנים יותר מ-N ימים זכאיות לחלוקת הכנסות. מיושם באמצעות חותמת הזמן של ההעברה האחרונה.
פתרון 3: Snapshot מסוג commit-reveal. רגע ה-snapshot אינו ידוע מראש; הוא נקבע באקראי או עם עיכוב. התוקף לא יכול להתכונן.
// Пример minimum holding period mapping(address => uint256) public lastReceived; function _afterTokenTransfer(address, address to, uint256) internal override { lastReceived[to] = block.timestamp; } function isEligible(address holder) public view returns (bool) { return lastReceived[holder] <= block.timestamp - MIN_HOLD_DURATION; } כיצד להפחית גז בעת פריסה?
השתמש ב-Foundry לפריסה עם אופטימיזציה של bytecode. בחר מודל עם עלות גז נמוכה לתביעה—Synthetix rewards מספק חיסכון פי 10 עבור מספר גדול של תביעות בהשוואה לחלוקת Merkle.
מה כולל פיתוח מערכת חלוקת הכנסות?
הצוות שלנו מספק מחזור עבודה מלא עם תוצרים ברורים:
- עיצוב ארכיטקטוני: בחירת מודל, חישובי גז, ניתוח אבטחה
- פיתוח חוזים חכמים ב-Solidity עם כיסוי בדיקות מלא (Foundry, Hardhat)
- תשתית off-chain: צינור snapshot, יצירת עץ Merkle, API להוכחות (Node.js/Python)
- ביקורת אבטחה: ניתוח סטטי (Slither, Mythril), fuzzing (Echidna), סקירה ידנית—מבטיחה מציאת בעיות קריטיות
- פריסה והגדרה: mainnet/testnet, multisig, Timelock
- תיעוד: מפרט טכני (PDF), מדריך משתמש, הערות קוד, תיעוד API
- גישה: מאגר GitHub, סקריפטי פריסה, לוח בקרה למנהל (אם רלוונטי)
- הדרכה: מפגש של שעתיים לצוות שלך על תפעול ותחזוקת המערכת
- תמיכה לאחר השקה: 30 ימי ניטור, עדכונים, תיקונים חמים
תוכנית פיתוח שלב אחר שלב
- ניתוח דרישות—קביעת מספר מחזיקים, תדירות תשלומים, טוקנים לחלוקה.
- עיצוב ארכיטקטורה—בחירת מודל, תכנון חוזים חכמים ורכיבי off-chain.
- פיתוח חוזים חכמים—כתיבת קוד Solidity עם בדיקות ב-Foundry/Hardhat.
- אינטגרציית off-chain—יישום צינור snapshot, יצירת עץ Merkle, API.
- ביקורת אבטחה—ביצוע ניתוח סטטי ו-fuzzing.
- פריסה והגדרה—פריסה ב-mainnet, הגדרת multisig ו-Timelock.
- תמיכה וניטור—הבטחת פעולה יציבה לאחר ההשקה.
להערכת הפרויקט שלך, קבל ייעוץ על ארכיטקטורת חלוקת הכנסות—נכין הצעה תוך יום אחד. דון בפרטי הפרויקט שלך כדי להזמין פיתוח.
פרמטרי בחירה מעשיים
אם מחזיקים < 1,000 וההכנסות מחולקות בתדירות גבוהה—תגמולי staking בסגנון Synthetix. אם מחזיקים > 10,000 והחלוקה מחזורית—חלוקת Merkle. אם נדרשת גמישות (טוקנים שונים, כללי זכאות שונים)—תכנית היברידית עם snapshot off-chain ואימות on-chain.
| שיטת הגנה | מורכבות | יעילות |
|---|---|---|
| יתרה משוקללת בזמן | בינונית | גבוהה |
| תקופת החזקה מינימלית | נמוכה | בינונית |
| Snapshot מסוג commit-reveal | גבוהה | גבוהה מאוד |
לוח זמנים לפיתוח: 3–5 שבועות למערכת בסיסית, 6–9 שבועות עם תגמולים מרובים, הגנה נגד flash loan ולוח בקרה frontend. להערכה מדויקת, צור קשר—ננתח את הדרישות שלך תוך יום אחד.







