פיתוח פלטפורמת Launchpad מותאמת אישית למכירות טוקנים

השקת מכירת טוקנים דורשת תשתית אמינה שמגנה מפני בוטים והתקפות, תוך שמירה על חוויית משתמש ידידותית. אנחנו מפתחים פלטפורמות launchpad במחזור מלא: מחוזים חכמים ועד frontend ותמיכה. הצוות שלנו מספק פרויקטים turnkey, ומבטיח אבטחה וסקלביליות לפתרון שלכם.

שירותי פיתוח בלוקצ'יין

שאלות נפוצות

העבודות האחרונות

  • פיתוח אתר חברה B2B ADVANCE
    פיתוח אתר חברה B2B ADVANCE
    1481
  • פיתוח אפליקציית ווב עבור FEEDME
    פיתוח אפליקציית ווב עבור FEEDME
    1335
  • פיתוח אתר עבור BELFINGROUP
    פיתוח אתר עבור BELFINGROUP
    1034
  • פיתוח חנות מקוונת לחברת FURNORO
    פיתוח חנות מקוונת לחברת FURNORO
    1293
  • עיצוב לוגו לחברת B2B Advance
    עיצוב לוגו לחברת B2B Advance
    738
  • פיתוח אפליקציית ווב עבור Enviok
    פיתוח אפליקציית ווב עבור Enviok
    1031

אנחנו בונים פלטפורמות Launchpad למכירות טוקנים

פלטפורמות Launchpad למכירות טוקנים דורשות איזון עדין: הן חייבות להיות פתוחות מספיק כדי למשוך משתתפים, אך עמידות בפני MEV, סנייפינג והתקפות Sybil. הצוות שלנו עבד למעלה מ-7 שנים ב-DeFi והשיק 15+ פרויקטי Launchpad שגייסו יחד למעלה מ-500 מיליון דולר. Launchpad טיפוסי מושך בין 500,000 ל-50 מיליון דולר, והארכיטקטורה שלנו מפחיתה עלויות עסקה ב-25% באמצעות חוזים חכמים אופטימליים.

למה Launchpad הוא יותר מסתם חוזה

חוזים חכמים הם רק חצי מהסיפור. Launchpad ברמת ייצור כולל ממשק משתתף ומנהל, אינטגרציית KYC, יצירת Merkle Tree לרשימות לבנות, backend לניטור ומודל כלכלת פלטפורמה. כל פרט משפיע על אבטחה וחוויית משתמש. לפי הנתונים שלנו, 70% מזמן הפיתוח מושקע ב-backend וב-UX, לא בחוזים חכמים.

מכניקות מפתח של פלטפורמות Launchpad למכירות טוקנים

מבני מכירה

אנחנו מיישמים שלושה מודלי מכירה עיקריים, לכל אחד מכניקה משלו:

מכירה במחיר קבוע

המודל הפשוט ביותר. המחיר קבוע, והמשתתפים הראשונים X מקבלים הקצאות. בעיה: בוטים תופסים הקצאות בבלוק הראשון. הפתרון שלנו: רשימה לבנה מבוססת Merkle ומגבלות לכל בלוק.

מודל Overflow / הרשמת יתר

משתתפים יכולים לתרום כל סכום, והמחיר הסופי נקבע לפי הנפח הכולל. אם היעד נרשם יתר על המידה פי 3, כל משתתף מקבל 1/3 מהתרומה שלו בחזרה והשאר מומר לטוקנים. מודל זה משמש פלטפורמות כמו Polkastarter ו-CoinList.

מכירה פומבית הולנדית

המחיר מתחיל גבוה ויורד עד שכל ההיצע נמכר. זה מגלה את "המחיר ההוגן" של השוק ועמיד בפני סנייפינג. למידע נוסף ראו ויקיפדיה: מכירה פומבית הולנדית.

// Dutch Auction sale contract
contract DutchAuctionSale {
    uint256 public immutable startPrice;
    uint256 public immutable endPrice;
    uint256 public immutable startTime;
    uint256 public immutable endTime;
    uint256 public immutable totalTokensForSale;
    uint256 public tokensSold;
    mapping(address => uint256) public contributions;

    function currentPrice() public view returns (uint256) {
        if (block.timestamp <= startTime) return startPrice;
        if (block.timestamp >= endTime) return endPrice;
        uint256 elapsed = block.timestamp - startTime;
        uint256 duration = endTime - startTime;
        uint256 priceDrop = startPrice - endPrice;
        return startPrice - (priceDrop * elapsed / duration);
    }

    function buy(uint256 tokenAmount) external payable nonReentrant {
        require(block.timestamp >= startTime && block.timestamp <= endTime, "Not active");
        uint256 price = currentPrice();
        uint256 cost = tokenAmount * price / 1e18;
        require(msg.value >= cost, "Insufficient ETH");
        require(tokensSold + tokenAmount <= totalTokensForSale, "Exceeds supply");
        tokensSold += tokenAmount;
        contributions[msg.sender] += tokenAmount;
        // Возврат излишка
        if (msg.value > cost) {
            payable(msg.sender).transfer(msg.value - cost);
        }
    }
}

השוואת מודלי מכירה

מודל יתרונות חסרונות מתי להשתמש
מחיר קבוע יישום פשוט בוטים, חלוקה לא הוגנת משקיעים מוקדמים עם רשימה לבנה
Overflow עמיד בפני בוטים, חלוקה הוגנת קשה יותר להבנה IDOs המוניים
מכירה פומבית הולנדית גילוי מחיר איטי, יישום מורכב פרויקטים גדולים

רשימה לבנה והקצאה

רשימה לבנה מבוססת Merkle Tree

התקן לרשימות לבנות חסכוניות בגז. רשימת הכתובות מאוחסנת מחוץ לרשת; רק השורש נשמר על הרשת. משתתף מספק הוכחה בעת רכישה:

import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";

bytes32 public merkleRoot;

function buyWithWhitelist(
    uint256 tokenAmount,
    uint256 maxAllocation, // аллокация для этого адреса (из листа)
    bytes32[] calldata merkleProof
) external payable {
    // Верифицируем что адрес в whitelist с указанной аллокацией
    bytes32 leaf = keccak256(abi.encodePacked(msg.sender, maxAllocation));
    require(
        MerkleProof.verify(merkleProof, merkleRoot, leaf),
        "Not whitelisted or wrong allocation"
    );
    require(
        contributions[msg.sender] + tokenAmount <= maxAllocation,
        "Exceeds allocation"
    );
    // ... логика покупки
}

עדכון שורש ה-Merkle זול יותר מאשר שמירת מיפוי על הרשת של כל הכתובות.

הקצאה מדורגת

מודל המשמש Launchpads מובילים (DAO Maker, GameFi, RedKite): גודל ההקצאה תלוי בכמות הטוקנים של הפלטפורמה שה-Staking עליהם. משתתפים מחולקים לדרגות (ברונזה/כסף/זהב/יהלום), כל אחת עם הקצאה מובטחת יחסית ל-Stake שלהם.

struct TierConfig {
    uint256 minStake; // минимальный стейк для входа в тир
    uint256 allocationMultiplier; // в basis points, 10000 = 1x
    uint256 guaranteedSlots; // гарантированные слоты (0 = lottery)
}

TierConfig[] public tiers;

function getUserTier(address user) public view returns (uint256) {
    uint256 staked = stakingContract.stakedAmount(user);
    for (uint256 i = tiers.length; i > 0; i--) {
        if (staked >= tiers[i-1].minStake) return i-1;
    }
    return type(uint256).max; // не в тире
}

function getUserAllocation(address user) public view returns (uint256) {
    uint256 tierIndex = getUserTier(user);
    if (tierIndex == type(uint256).max) return 0;
    uint256 baseAllocation = totalSaleAmount / totalWhitelistedUsers;
    return baseAllocation * tiers[tierIndex].allocationMultiplier / 10000;
}

Vesting ותביעה

לאחר IDO, טוקנים בדרך כלל לא מחולקים מיד – זה תקן בתעשייה. Vesting טיפוסי ל-Launchpad: 20% ב-TGE, השאר ליניארי על פני 6–12 חודשים.

contract TokenVesting {
    struct VestingSchedule {
        uint256 totalAmount;
        uint256 claimedAmount;
        uint256 tgePercent; // % доступный сразу после TGE
        uint256 cliffDuration; // задержка перед линейным вестингом
        uint256 vestingDuration; // длительность линейного вестинга
        uint256 tgeTimestamp;
    }

    mapping(address => VestingSchedule) public schedules;

    function claimableAmount(address beneficiary) public view returns (uint256) {
        VestingSchedule storage schedule = schedules[beneficiary];
        if (schedule.totalAmount == 0) return 0;

        uint256 tgeAmount = schedule.totalAmount * schedule.tgePercent / 10000;
        if (block.timestamp < schedule.tgeTimestamp) {
            return 0;
        }

        uint256 cliffEnd = schedule.tgeTimestamp + schedule.cliffDuration;
        if (block.timestamp < cliffEnd) {
            return tgeAmount > schedule.claimedAmount ? tgeAmount - schedule.claimedAmount : 0;
        }

        uint256 vestingStart = cliffEnd;
        uint256 vestingEnd = vestingStart + schedule.vestingDuration;
        uint256 elapsed = min(block.timestamp, vestingEnd) - vestingStart;
        uint256 vestedLinear = (schedule.totalAmount - tgeAmount) * elapsed / schedule.vestingDuration;
        uint256 totalVested = tgeAmount + vestedLinear;
        return totalVested > schedule.claimedAmount ? totalVested - schedule.claimedAmount : 0;
    }

    function claim() external nonReentrant {
        uint256 amount = claimableAmount(msg.sender);
        require(amount > 0, "Nothing to claim");
        schedules[msg.sender].claimedAmount += amount;
        saleToken.safeTransfer(msg.sender, amount);
        emit TokensClaimed(msg.sender, amount);
    }
}

איך אנחנו מגנים על ה-Launchpad מפני בוטים

בוטים עוקבים אחר ה-mempool ומנסים לקנות בבלוק הראשון של מכירה. אנחנו משתמשים בשילוב של הגנות:

  1. // Dutch Auction sale contract DutchAuctionSale { uint256 public immutable startPrice; uint256 public immutable endPrice; uint256 public immutable startTime; uint256 public immutable endTime; uint256 public immutable totalTokensForSale; uint256 public tokensSold; mapping(address => uint256) public contributions; function currentPrice() public view returns (uint256) { if (block.timestamp <= startTime) return startPrice; if (block.timestamp >= endTime) return endPrice; uint256 elapsed = block.timestamp - startTime; uint256 duration = endTime - startTime; uint256 priceDrop = startPrice - endPrice; return startPrice - (priceDrop * elapsed / duration); } function buy(uint256 tokenAmount) external payable nonReentrant { require(block.timestamp >= startTime && block.timestamp <= endTime, "Not active"); uint256 price = currentPrice(); uint256 cost = tokenAmount * price / 1e18; require(msg.value >= cost, "Insufficient ETH"); require(tokensSold + tokenAmount <= totalTokensForSale, "Exceeds supply"); tokensSold += tokenAmount; contributions[msg.sender] += tokenAmount; // Возврат излишка if (msg.value > cost) { payable(msg.sender).transfer(msg.value - cost); } } } – משתתף שולח תחילה import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol"; bytes32 public merkleRoot; function buyWithWhitelist( uint256 tokenAmount, uint256 maxAllocation, // аллокация для этого адреса (из листа) bytes32[] calldata merkleProof ) external payable { // Верифицируем что адрес в whitelist с указанной аллокацией bytes32 leaf = keccak256(abi.encodePacked(msg.sender, maxAllocation)); require( MerkleProof.verify(merkleProof, merkleRoot, leaf), "Not whitelisted or wrong allocation" ); require( contributions[msg.sender] + tokenAmount <= maxAllocation, "Exceeds allocation" ); // ... логика покупки } , ואז חושף struct TierConfig { uint256 minStake; // минимальный стейк для входа в тир uint256 allocationMultiplier; // в basis points, 10000 = 1x uint256 guaranteedSlots; // гарантированные слоты (0 = lottery) } TierConfig[] public tiers; function getUserTier(address user) public view returns (uint256) { uint256 staked = stakingContract.stakedAmount(user); for (uint256 i = tiers.length; i > 0; i--) { if (staked >= tiers[i-1].minStake) return i-1; } return type(uint256).max; // не в тире } function getUserAllocation(address user) public view returns (uint256) { uint256 tierIndex = getUserTier(user); if (tierIndex == type(uint256).max) return 0; uint256 baseAllocation = totalSaleAmount / totalWhitelistedUsers; return baseAllocation * tiers[tierIndex].allocationMultiplier / 10000; } ו-contract TokenVesting { struct VestingSchedule { uint256 totalAmount; uint256 claimedAmount; uint256 tgePercent; // % доступный сразу после TGE uint256 cliffDuration; // задержка перед линейным вестингом uint256 vestingDuration; // длительность линейного вестинга uint256 tgeTimestamp; } mapping(address => VestingSchedule) public schedules; function claimableAmount(address beneficiary) public view returns (uint256) { VestingSchedule storage schedule = schedules[beneficiary]; if (schedule.totalAmount == 0) return 0; uint256 tgeAmount = schedule.totalAmount * schedule.tgePercent / 10000; if (block.timestamp < schedule.tgeTimestamp) { return 0; } uint256 cliffEnd = schedule.tgeTimestamp + schedule.cliffDuration; if (block.timestamp < cliffEnd) { return tgeAmount > schedule.claimedAmount ? tgeAmount - schedule.claimedAmount : 0; } uint256 vestingStart = cliffEnd; uint256 vestingEnd = vestingStart + schedule.vestingDuration; uint256 elapsed = min(block.timestamp, vestingEnd) - vestingStart; uint256 vestedLinear = (schedule.totalAmount - tgeAmount) * elapsed / schedule.vestingDuration; uint256 totalVested = tgeAmount + vestedLinear; return totalVested > schedule.claimedAmount ? totalVested - schedule.claimedAmount : 0; } function claim() external nonReentrant { uint256 amount = claimableAmount(msg.sender); require(amount > 0, "Nothing to claim"); schedules[msg.sender].claimedAmount += amount; saleToken.safeTransfer(msg.sender, amount); emit TokensClaimed(msg.sender, amount); } } בשלב הבא. בוטים לא יכולים לדעת את הסכום המדויק עד לחשיפה.
  2. Commit-reveal – זמן ההתחלה המדויק נדחה בעיכוב אקראי (למשל, 0–300 שניות) באמצעות Chainlink VRF.
  3. commit = keccak256(amount, salt, address) – לא יותר מ-X רכישות לכל בלוק, או סכום מקסימלי לכל בלוק:
uint256 public maxContributionPerBlock;
mapping(uint256 => uint256) public blockContributions;

function buy(uint256 amount) external payable {
    require(
        blockContributions[block.number] + amount <= maxContributionPerBlock,
        "Block limit reached"
    );
    blockContributions[block.number] += amount;
    // ...
}

הפסדים מבוטים יכולים להגיע עד 2 מיליון דולר למכירה – ההגנות שלנו נועדו למנוע זאת.

אינטגרציית KYC

לשווקים מפוקחים, אנחנו משתלבים עם ספקי KYC. הממשק אוסף נתוני KYC (באמצעות Sumsub, Onfido או Synaps) ומנפיק JWT חתום. ה-backend שלנו מאמת את ה-JWT ומוסיף את הכתובת לרשימה הלבנה באמצעות עסקה.

גישה יותר על הרשת משתמשת ב-Verifiable Credentials: ספק ה-KYC מנפיק VC, והמשתמש מספק הוכחת ZK שהוא מחזיק ב-VC תקף מבלי לחשוף נתונים אישיים. יישומים כוללים Polygon ID ו-Worldcoin (עם שיקולי פרטיות).

איך להקים רשימה לבנה מבוססת Merkle ב-5 שלבים

  1. אספו את רשימת הכתובות וההקצאות שלהם בקובץ CSV.
  2. צרו Merkle tree באמצעות סקריפט (למשל, Node.js עם ethers.js).
  3. העלו את ה-hash של השורש לחוזה במהלך הפריסה.
  4. לכל משתתף, צרו הוכחה (קבוצת hashes) והעבירו אותה דרך הממשק.
  5. המשתתף קורא ל-amount עם ההוכחה, הסכום וההקצאה. החוזה מאמת את ההוכחה ומאפשר את הרכישה.

פאנל ניהול וניהול רישומים

Launchpad הוא לא רק חוזים חכמים. מוצר מלא כולל: לפרויקטים (רישום):

  • טופס הגשה עם אימות חוזה טוקן
  • זרימת עבודה למנהל לאישור/דחייה
  • הגדרת פרמטרי מכירה: מחיר, תקרה קשיחה, תקרה רכה, תאריכים, רשימה לבנה, Vesting
  • העלאת CSV של רשימה לבנה → יצירת Merkle tree

למשתתפים:

  • לוח מחוונים עם מכירות פעילות ועבר
  • תהליך KYC
  • הרשמה לרשימה לבנה עם ארנק מחובר
  • ממשק תביעה עם לוח זמנים של Vesting

למנהלים:

  • ניטור התקדמות מכירה בזמן אמת
  • השהיית חירום
  • ניהול רשימה לבנה (הוספה/הסרה)
  • משיכת כספים שגויסו לאחר סיום

כלכלת פלטפורמה

Launchpads בדרך כלל מנטרלים רווח באמצעות:

  • אחוז מהגיוס – 3–8% מהכספים שנאספו
  • הקצאת טוקנים – X% מהטוקנים של הפרויקט
  • טוקן פלטפורמה – Staking להקצאות (נעילת אקוסיסטם)

שלבי פיתוח

שלב תוכן משך
עיצוב מכניקת מכירה, לוחות זמנים של Vesting, מבנה דרגות, טוקנומיקה 2–3 שבועות
חוזי ליבה מכירה, Vesting, Staking, רשימה לבנה 4–5 שבועות
בדיקות יחידה, אינטגרציה, בדיקות fork, fuzz 2–3 שבועות
Backend API, יצירת Merkle tree, אינטגרציית KYC 3–4 שבועות
Frontend לוח מחוונים למשתתף, פאנל מנהל 4–5 שבועות
ביקורת חוזים + backend 3–4 שבועות
פיילוט Testnet IDO אחד לבדיקה 2–3 שבועות

סה"כ: 20–27 שבועות. ביקורת היא קריטית – Launchpads מחזיקים בכספי משתתפים והם יעדים עיקריים להתקפות.

מה כלול בעבודה שלנו

  • חוזים חכמים עם קוד מקור ותיעוד
  • תיעוד ארכיטקטוני ודיאגרמות
  • פאנל Frontend למשתתפים ומנהלים
  • אינטגרציית ספק KYC
  • הגדרת Merkle tree לרשימה לבנה
  • סקריפטים לפריסה ומיגרציות
  • דוחות ביקורת (ביקורת חיצונית)
  • 3 חודשים של תמיכה טכנית לאחר ההשקה

העריכו את המומחיות שלנו – הזמינו ייעוץ. צרו קשר כדי לדון בארכיטקטורת ה-Launchpad שלכם. הזמינו פיתוח turnkey עם ביקורת ותמיכה טכנית.