إنتقل إلى المحتوى الرئيسي

Microsales

عنوان العقد

لا تملك الـ microsales عقدًا خاصًا بها. فهي تشترك في عنوان الـ launchpad الوحيد مع pools وMelt Pools — عنوان واحد لكل شبكة، وABI واحد، وأنماط الإطلاق الثلاثة جميعها.

الشبكةChain IDLaunchpad
BNB Chain (mainnet)560xD9CcE715619fA9082d21375B6B37A3a0d99138F4
BNB Chain (testnet)970x0AA21d47b600B04527c09BbD9A30aF32cb64f6cF
Robinhood Chain46630x7E0752B42f9db92F12E221E10fFfa10bfE8668C6

يُحدَّد كل microsale على حدة بعنوان fundManager الخاص به، وهو ما تمرره كوسيط إلى الاستدعاءات أدناه. هذا مقبض خاص بكل بيع، وليس عقدًا تستدعيه.

الـ microsale هو بيع توكن بسعر ثابت. تختار قالب إعدادات (config template)، ويقوم الـ launchpad بسكّ توكن جديد، ويرسل المساهمون أموالهم حتى يتم الوصول إلى السقف الأقصى (hard cap)، وعند الإنهاء (finalize) يقوم الـ launchpad بإدراج التوكن عبر إضافة سيولة إلى DEX. كل microsale ينشئ توكنًا واحدًا بالضبط، ولا يمكن إطلاق التوكن عبر microsale إلا مرة واحدة.

تستعرض هذه الصفحة دورة الحياة كاملة: اختيار قالب، الإنشاء، المساهمة، الإنهاء، المطالبة (claim)، والتعامل مع الاسترداد. الإطلاقات المدعومة بـ vault لها صفحتها الخاصة، vaults.md، لكن استدعاء الإنشاء ملخّص هنا أيضًا.

المحتويات​

الأجزاء المكوّنة​

  • الإعدادات (القالب). تنشر المنصة قوالب قابلة لإعادة الاستخدام تحدّد الاقتصاديات: كم عدد التوكنات المخصصة للبيع المسبق، وكم منها للسيولة، والسقف الأقصى، ومدة البيع. تطلق الإطلاق مقابل قالب معيّن عبر configId الخاص به.
  • البيع. نسخة واحدة تُنشأ من قالب. يُحدَّد بعنوان fundManager الخاص به.
  • التوكن. يُسكّ عند الإنشاء. إجمالي العرض ثابت عند 1,000,000,000 (1e27 مع 18 خانة عشرية) ومقسّم بين البيع المسبق والسيولة (LP) حسب القالب.
  • مدير الأموال (fundManager). عنوان خاص بكل بيع يحتفظ بالتمويل والتوكن حتى الإنهاء. لن تستدعيه مباشرةً أبدًا. إنه المقبض (handle) الذي تمرره إلى كل دالة microsale تقريبًا، والأحداث الرئيسية مفهرسة به.

حالات البيع​

يكون الـ microsale دائمًا في إحدى ثلاث حالات:

الحالةالقيمةالمعنى
Active0مفتوح للمساهمات
Finalized1تم الوصول إلى السقف الأقصى، أُضيفت السيولة، والتوكنات قابلة للمطالبة
Cancelled2تم الإلغاء؛ يمكن للمساهمين السحب

تفصيل مهم: لا ينتهي الـ microsale إلا عندما يصل التمويل المُجمّع إلى السقف الأقصى بالضبط. المساهمات مُقيّدة بحيث لا يمكن أن يتجاوز totalRaised قيمة hardCap أبدًا، والمساهمة الأخيرة التي تسدّ الفجوة تحدد filledAt. البيع الذي يصل إلى وقت انتهائه دون أن يمتلئ يبقى Active لكنه يصبح قابلًا للاسترداد (راجع الاسترداد والخروج).

قوالب الإعدادات​

أنت لا تحدد اقتصاديات البيع؛ تختار من بين قوالب تنشرها المنصة. اكتشفها قبل عرض نموذج الإنشاء:

// Full template objects (recommended for discovery)
const configs = await launchpad.getActiveMicroSaleConfigs();

for (const c of configs) {
console.log({
configId: c.configId,
presaleTokens: c.presaleTokens,
lpTokens: c.lpTokens,
hardCap: c.hardCap, // in the template's raise currency
duration: c.duration, // seconds
active: c.active,
});
}

قراءات ذات صلة:

الدالةتُرجع
getActiveMicroSaleConfigs()مصفوفة من MicroSaleConfig النشطة
getActiveMicroSaleConfigIds()مصفوفة من قيم configId النشطة
getMicroSaleConfig(configId)قالب واحد
getMicroSaleConfigsCount()إجمالي القوالب التي أُنشئت على الإطلاق

السعر مُشتق من القالب​

أنت لا تحدد سعرًا. يحسب الـ launchpad معدّلين من القالب والسقف الأقصى:

  • معدّل البيع المسبق (Presale rate) = presaleTokens * 1e18 / hardCap. هذا هو عدد وحدات التوكن التي يحصل عليها المساهم لكل وحدة من عملة التمويل: purchased = amount * rate / 1e18.
  • معدّل الإدراج (Listing rate) = lpTokens * 1e18 / (hardCap * 0.95). هذا يحدد سعر الافتتاح على DEX. نسبة الـ 0.95 هي رسوم المنصة البالغة 5% المقتطعة من التمويل قبل إضافة السيولة.

عملة التمويل​

معظم القوالب تجمع التمويل بعملة السلسلة الأصلية (BNB). بعض القوالب مرتبطة بتوكن ERC20 للتسعير بدلًا من ذلك. تحقق من الارتباط قبل الإنشاء أو المساهمة:

const quote = await launchpad.getMicroSaleConfigQuoteToken(configId);
// address(0) => native (BNB) raise
// otherwise => contributors pay with that ERC20

ينطبق الارتباط على الإطلاقات بلا ضريبة، وبمستلم-محفظة، وبـ vault. التمويل الأصلي (native) يستخدم contributeMicroSale؛ أما تمويل ERC20 فيستخدم contributeMicroSaleQuote. مزجهما يؤدي إلى فشل التنفيذ (revert).

توكنات التسعير المسموح بها​

تجمع الـ microsales ومنحنيات Melt Pool التمويل بعملة السلسلة الأصلية أو بأي توكن على قائمة السماح المشتركة لتوكنات التسعير الخاصة بالـ launchpad — اقرأها مباشرةً عبر getAllowedQuoteTokens() وتحقق من توكن واحد عبر isQuoteTokenAllowed(token). راجع العملات المدعومة للقائمة الكاملة لكل سلسلة.

أنواع التوكن ومسارات الإنشاء​

هناك ثلاثة مسارات إنشاء حالية. كل واحد يُرجع عنوان fundManager الخاص بالبيع الجديد.

الدالةالتوكنالضريبةعملة التمويلمستلم الرسوم
createMicroSaleNoTaxTokenCheeseTokenلا يوجدأصلية أو ERC20 حسب القالبلا ينطبق
createMicroSaleTaxTokenV2CheeseTaxTokenV2ضريبة شراء/بيعأصلية أو ERC20 حسب القالبمحفظة تسمّيها أنت
createMicroSaleTaxTokenWithVaultV2CheeseTaxTokenV2ضريبة شراء/بيعأصلية أو ERC20 حسب القالبvault يُنشر عند الإطلاق

مسارات التوكن الضريبي تسكّ توكنًا يفرض ضريبة على عمليات الشراء والبيع ويوجّه تلك الإيرادات إلى مستلم رسوم. المسار العادي يسكّ ERC20 عاديًا بلا ضريبة وبلا مستلم رسوم. اختر مسار الـ vault عندما تريد أن تتدفق الإيرادات إلى منطق دفع قابل للبرمجة؛ راجع vaults.md.

التحقق من مصدر التوكن​

كل توكن يسكّه microsale هو أحد عقدين: ERC20 العادي (CheeseToken) أو ERC20 الذي يجمع الضريبة (CheeseTaxTokenV2). الكود المصدري لكليهما منشور في cheesepad-ai/cheesepad-contracts. ملفات ABI القابلة للتنزيل ودوال القراءة الخاصة بكل توكن مشروحة في التوكنات المسكوكة. ينطبق هذا أيضًا على التوكنات التي تسكّها Melt Pools.

إنشاء microsale​

المعاملات المشتركة​

كل استدعاء إنشاء يأخذ هذه الحقول (داخل CreateParams):

الحقلالنوعملاحظات
configIduint256القالب المُراد الإطلاق مقابله؛ يجب أن يكون نشطًا
namestringاسم التوكن
symbolstringرمز التوكن
poolDetailsstringبيانات وصفية حرة الشكل (JSON، رابط، أو أي شيء تخزّنه واجهتك)
maxContributionuint256سقف تراكمي للمساهمة لكل عنوان؛ 0 تعني بلا حدود
saltbytes32ملح CREATE2 جديد تُرجعه CheesePad API
lockDurationuint256مدة قفل السيولة (LP) بالثواني؛ 0 تحرق السيولة بدلًا من قفلها

قواعد lockDuration: إما 0 (تُحرق السيولة عند الإنهاء) أو بين الحد الأدنى للسلسلة (365 يومًا على كلتا الشبكتين الرئيسيتين، و5 دقائق على BNB testnet) وسقف 10 سنوات. أي قيمة أخرى تؤدي إلى فشل التنفيذ برسالة Invalid lock duration.

إذا كانت المنصة تفرض رسوم إنشاء، أرسلها كـ msg.value في استدعاء الإنشاء (راجع getting-started.md).

توليد ملح التوكن​

اطلب ملحًا جديدًا مباشرةً قبل كل استدعاء إنشاء. تحتوي الاستجابة أيضًا على عنوان التوكن الذي سينشره الـ launchpad. لا تعِد استخدام ملح لإطلاق آخر.

type SaltTokenType = "CheeseToken" | "CheeseTaxTokenV2";

async function generateTokenSalt(
tokenType: SaltTokenType,
name: string,
symbol: string,
router: string,
): Promise<{ salt: string; address: string }> {
const { chainId } = await provider.getNetwork();
const query = new URLSearchParams({
tokenType,
launchpadContract: LAUNCHPAD,
chainId: chainId.toString(),
name,
symbol,
router,
});

const response = await fetch(
`https://api.cheesepad.ai/microsale/generate-salt?${query}`,
);
if (!response.ok) {
throw new Error(`Salt generation failed: ${response.status} ${await response.text()}`);
}
return response.json();
}

مرّر أحد الراوترات المدعومة من الـ launchpad. لإطلاق توكن V2 ضريبي، استخدم نفس dexKey الذي تمرره إلى دالة الإنشاء. تُرجع الـ API دائمًا salt بطول 32 بايت وaddress المقابل له.

اختيار DEX لتوكن ضريبي​

يأخذ استدعاءا توكن V2 الضريبي dexKey بعد بقية وسائطهما. استخدم راوترًا مدعومًا يكون مدخل الـ DEX الخاص به مُفعَّلًا:

const [dexKey] = await launchpad.getSupportedRouters();
const dex = await launchpad.getDex(dexKey);
if (!dex.enabled) throw new Error("DEX is not enabled");

يوفّر الـ launchpad إعداد منفذ تداول ذلك الـ DEX للتوكن. لا يحتاج المستدعون إلى اكتشاف أو حساب هاشات الأزواج أو مستويات الرسوم.

توكن بلا ضريبة​

الإطلاق الأبسط. يحدد القالب المختار ما إذا كان المساهمون يدفعون بالعملة الأصلية أو بتوكن ERC20 للتسعير.

const name = "My Token";
const symbol = "MTK";
const [router] = await launchpad.getSupportedRouters();
if (!router) throw new Error("No supported router");
const { salt, address: predictedToken } = await generateTokenSalt(
"CheeseToken",
name,
symbol,
router,
);

const params = {
configId: 0n,
name,
symbol,
poolDetails: "",
maxContribution: 0n, // unlimited per wallet
salt,
lockDuration: 0n, // burn LP at finalize
};

const creationFee = (await launchpad.getMasterConfig()).microSaleCreationFee;
const tx = await launchpadRW.createMicroSaleNoTaxToken(params, { value: creationFee });
const receipt = await tx.wait();

// The fundManager and token come from the MicroSaleCreated event
const ev = receipt.logs.find((l) => l.eventName === "MicroSaleCreated");
const fundManager = ev.args.fundManager;
const token = ev.args.token;
if (token.toLowerCase() !== predictedToken.toLowerCase()) {
throw new Error("Created token does not match the predicted address");
}

توكن ضريبي (مستلم رسوم عبارة عن محفظة)​

نفس الشكل مع إضافة taxConfig يصف الضريبة ووجهتها. تُرسَل الإيرادات إلى محفظة عادية تسمّيها أنت.

const name = "Taxed";
const symbol = "TAX";
const { salt, address: predictedToken } = await generateTokenSalt(
"CheeseTaxTokenV2",
name,
symbol,
dexKey,
);

const taxConfig = {
buyTaxBps: 300n, // 3% on buys; each side max 1000 (10%)
sellTaxBps: 500n, // 5% on sells; at least one side must be > 0
taxDuration: 365n * 24n * 60n * 60n, // required; seconds after listing
antiFarmerDuration: 15n * 60n, // taxes every registered venue during this window
allocation: { // must sum to 10000
feeReceiver: 10000, // 100% to the fee receiver in this example
holders: 0,
burn: 0,
liquidity: 0,
},
feeReceiver: "0xYourRevenueWallet",
quoteToken: ethers.ZeroAddress, // launchpad fills WETH for native templates
minHolderShare: 0n, // required > 0 only when holders > 0
v3Factory: ethers.ZeroAddress, // DEX-derived fields are filled by the launchpad
v2PairInitCodeHash: ethers.ZeroHash,
v3PoolInitCodeHash: ethers.ZeroHash,
v3FeeTiers: [],
};

const params = {
configId: 0n, name, symbol, poolDetails: "",
maxContribution: 0n, salt, lockDuration: 0n,
taxConfig,
};

const tx = await launchpadRW.createMicroSaleTaxTokenV2(params, dexKey, {
value: creationFee,
});

قواعد الضريبة المطبَّقة عند الإنشاء:

  • كل من buyTaxBps وsellTaxBps لا يتجاوز 1000 (10%)، ويجب أن يكون أحدهما على الأقل أعلى من صفر.
  • يجب أن تكون taxDuration أعلى من صفر ولا تقل عن antiFarmerDuration؛ وكلاهما محدود بسقف 150 عامًا.
  • يجب أن يساوي مجموع allocation.feeReceiver + holders + burn + liquidity القيمة 10000.
  • مستلم الرسوم لا يكسب إلا إذا كانت allocation.feeReceiver > 0، لذا فإن الإنشاء يفشل إذا حددت ضريبة لكن تركت هذه الحصة عند صفر (لن يتم تمويل المستلم أبدًا).
  • إذا كانت allocation.holders > 0، يجب عليك تحديد minHolderShare > 0 (الحد الأدنى للرصيد الذي تحتاجه المحفظة لكسب أرباح الحائزين).
  • عتبات تسييل الضريبة هي ثوابت في التوكن وليست معاملات إنشاء.

تسمح حصص allocation بأن يدفع توكن واحد لمحفظة، ويكافئ الحائزين كأرباح، ويحرق حصة، ويضيف إلى السيولة، كل ذلك من نفس الضريبة. لمسار المحفظة العادية يستخدم معظم الناس feeReceiver: 10000. حصص الحائزين/الحرق/السيولة مشروحة في vaults.md.

توكن ضريبي مع vault​

مستلم الرسوم هو vault يُنشر لك بواسطة مصنع (factory) تسمّيه. اضبط taxConfig.feeReceiver على العنوان الصفري؛ يربط الـ launchpad الـ vault المنشور. نظرًا لأن الوسائط الإضافية والتواصل مع المصنع (factory handshake) يحتاجان شرحًا خاصًا بهما، الشرح الكامل موجود في vaults.md. التوقيع هو:

function createMicroSaleTaxTokenWithVaultV2(
CreateParamsV2 calldata params,
address vaultFactory,
bytes calldata vaultData,
address dexKey
) external payable returns (address fundManager);

ولّد ملحًا منفصلًا لإطلاق الـ vault واضبط مستلم الرسوم على العنوان الصفري:

const { salt, address: predictedToken } = await generateTokenSalt(
"CheeseTaxTokenV2",
params.name,
params.symbol,
dexKey,
);
const vaultParams = {
...params,
salt,
taxConfig: { ...params.taxConfig, feeReceiver: ethers.ZeroAddress },
};

await launchpadRW.createMicroSaleTaxTokenWithVaultV2(
vaultParams,
VAULT_FACTORY,
vaultData,
dexKey,
{ value: creationFee },
);

قراءة ما أنشأته​

كل إنشاء يُصدر MicroSaleCreated(index, fundManager, owner, token, configId, timestamp). استخرج fundManager وtoken منه، أو ابحث عن البيع لاحقًا:

const sale = await launchpad.getMicroSaleByFundManager(fundManager);
// or by the token address, or by index
const sameByToken = await launchpad.getMicroSaleByToken(token);

المساهمة​

الدالة التي تستدعيها تعتمد على عملة التمويل الخاصة بالبيع. اقرأ sale.currency: address(0) تعني تمويلًا أصليًا، وأي شيء آخر يعني تمويل ERC20.

التمويل الأصلي (BNB)​

await launchpadRW.contributeMicroSale(fundManager, {
value: ethers.parseEther("1"), // 1 BNB
});

التمويل بعملة تسعير ERC20​

وافق على توكن التسعير أولًا، ثم ساهم بمبلغ محدد. لا msg.value.

const quote = new ethers.Contract(sale.currency, ERC20_ABI, signer);
await quote.approve(LAUNCHPAD, amount);
await launchpadRW.contributeMicroSaleQuote(fundManager, amount);

توكنات التسعير ذات الضريبة على التحويل (fee-on-transfer) مرفوضة: يتحقق الـ launchpad من أن المبلغ الذي استلمه يطابق amount بالضبط، وإلا يفشل التنفيذ برسالة Non-standard quote transfer.

ما يتحقق منه الـ launchpad عند كل مساهمة​

  • أن البيع في حالة Active.
  • أن الوقت الحالي ضمن [startTime, endTime).
  • أن totalRaised + amount <= hardCap (لا يمكنك تجاوز السقف).
  • إذا كانت maxContribution > 0، فإن مساهمتك التراكمية تبقى ضمن حدودها.
  • أن الشراء يُقرَّب إلى أكثر من صفر توكن (amount * rate / 1e18 > 0)، لذا فإن المبالغ التافهة تفشل برسالة Contribution too small.

نظرًا لأن المساهمات لا يمكن أن تتجاوز السقف الأقصى، فإن المبلغ الذي يسدّ الفتحة الأخيرة هو بالضبط hardCap - totalRaised. اعرض هذا الرقم لمستخدميك حتى لا تفشل معاملتهم.

const sale = await launchpad.getMicroSaleByFundManager(fundManager);
const remaining = sale.hardCap - sale.totalRaised;

let maxForUser = remaining;
if (sale.maxContribution > 0n) {
const me = await launchpad.getMicroSaleContribution(fundManager, myAddress);
const headroom = sale.maxContribution - me.contribution;
maxForUser = headroom < remaining ? headroom : remaining;
}

الإنهاء​

عند الوصول إلى السقف الأقصى، يقوم مالك البيع بإنهائه (يمكن لمشغّل المنصة القيام بذلك أيضًا، وهذا ما يسمح للواجهة بعرض خيار الإنهاء نيابةً عن المالك). الإنهاء يأخذ رسوم المنصة البالغة 5%، ويضيف باقي التمويل مع توكنات السيولة إلى DEX، ثم يقفل السيولة (إذا كانت lockDuration > 0) أو يحرقها.

const sale = await launchpad.getMicroSaleByFundManager(fundManager);
if (sale.totalRaised === sale.hardCap && sale.state === 0n) {
await launchpadRW.finalizeMicroSale(fundManager); // sale owner
}

بعد الإنهاء، تصبح sale.state تساوي 1 (Finalized)، وتصبح sale.listedAt هي طابع وقت الإدراج، وزوج DEX يصبح حيًا. هذه هي اللحظة التي يبدأ فيها التوكن بالتداول، لذا فهي الحدث الذي يجب مراقبته إذا كنت تتابع الإدراجات (MicroSaleFinalized).

المطالبة​

بمجرد إنهاء البيع، يطالب كل مساهم بالتوكنات التي اشتراها. المطالبة تحدث مرة واحدة فقط لكل عنوان.

await launchpadRW.claimMicroSale(fundManager); // sends msg.sender their tokens

const me = await launchpad.getMicroSaleContribution(fundManager, myAddress);
console.log("claimed:", me.claimed); // equals `purchased` after a successful claim

تفشل المطالبة إذا لم يُنهَ البيع بعد (MicroSale not finalized)، أو إذا لم تشترِ شيئًا (Nothing to claim)، أو إذا كنت قد طالبت مسبقًا (Already claimed).

الاسترداد والخروج​

هناك طريقتان لاستعادة الأموال، حسب الحالة.

استرداد كامل: بيع فاشل أو مُلغى​

تُعيد withdrawMicroSale 100% من المساهمة عندما:

  • يكون البيع لا يزال Active لكن endTime قد انقضى ولم يصل السقف الأقصى أبدًا (بيع فاشل)، أو
  • تم إلغاء البيع (Cancelled) من قِبل مالكه.
await launchpadRW.withdrawMicroSale(fundManager); // refunds msg.sender in full

هذا هو المسار الطبيعي لبيع لم يمتلئ. لا توجد رسوم.

خروج مبكر أثناء البيع النشط: السحب الطارئ​

تسمح emergencyWithdrawMicroSale للمساهم بمغادرة بيع لا يزال مفتوحًا ولم يمتلئ بعد، مقابل غرامة 10% (تذهب الغرامة إلى المنصة). محظورة في آخر 15 دقيقة قبل endTime.

await launchpadRW.emergencyWithdrawMicroSale(fundManager); // returns 90% to msg.sender

الشروط: البيع في حالة Active، لم يصل السقف الأقصى، لم ينتهِ البيع، وتبقى 15 دقيقة على الأقل. على عكس السحب الكامل، هذا يخفّض totalRaised الخاص بالبيع، ويحرّر تلك المساحة للآخرين.

إلغاء بيع​

يمكن للمالك إلغاء بيع Active، مما يحوّله إلى Cancelled ويفتح السحب الكامل لكل مساهم.

await launchpadRW.cancelMicroSale(fundManager); // sale owner

تعديل بيع​

يبقى حقلان قابلين للتعديل بعد الإنشاء من قِبل مالك البيع (أو مشغّل المنصة):

الدالةتُحدّث
updateMicroSaleDetails(fundManager, poolDetails)البيانات الوصفية الحرة؛ المالك يمكنه استدعاء هذا فقط أثناء كون البيع Active، أما المشغّل فيمكنه استدعاءه في أي وقت
setMicroSaleMaxContribution(fundManager, maxContribution)سقف المساهمة لكل عنوان؛ 0 تعني بلا حدود

كلاهما يُصدر MicroSaleUpdated(index, fundManager, timestamp).

قراءة حالة البيع​

كل ما تحتاجه للوحة معلومات هو استدعاء قراءة. جميعها مفتوحة للجميع.

البحث عن بيع​

الدالةالاستخدام
getMicroSale(index)حسب فهرس الإنشاء
getMicroSaleByFundManager(fundManager)حسب مقبض البيع
getMicroSaleByToken(token)حسب عنوان التوكن (بعلاقة 1:1 مع البيع)
getMicroSaleByVault(vault)حسب الـ vault المرتبط، لإطلاقات الـ vault
getMicroSalesCount()إجمالي المبيعات التي أُنشئت على الإطلاق
isQuoteTokenAllowed(token)ما إذا كان ERC20 مقبولًا كتوكن تسعير لإطلاق عبر vault
getAllowedQuoteTokens()كل توكن ERC20 تقبله المنصة كتوكن تسعير

تحمل بنية MicroSale المُعادة الحالة الكاملة: state، totalRaised، hardCap، startTime، endTime، filledAt، listedAt، rate، maxContribution، token، currency، vault، والمزيد. راجع events-and-data.md لكل حقل.

البحث عن المساهمين​

// One user's ledger
const info = await launchpad.getMicroSaleContribution(fundManager, user);
// { contribution, purchased, claimed, excessiveRefunded }

// How many contributors
const n = await launchpad.getMicroSaleContributorCount(fundManager);

// A page of contributors (inclusive indexes; endIndex is clamped to the last one)
const page = await launchpad.getMicroSaleContributionInfos(fundManager, 0, 49);
// [{ user, contribution, purchased, claimed }, ...]

مساعد بسيط للتقدّم​

async function progress(fundManager: string) {
const s = await launchpad.getMicroSaleByFundManager(fundManager);
const pct = (Number(s.totalRaised) / Number(s.hardCap)) * 100;
return {
state: ["Active", "Finalized", "Cancelled"][Number(s.state)],
raised: ethers.formatEther(s.totalRaised),
hardCap: ethers.formatEther(s.hardCap),
percent: pct.toFixed(2),
endsIn: Number(s.endTime) - Math.floor(Date.now() / 1000),
};
}

عناوين توكن مميزة (vanity)​

كل مسار إنشاء ينشر التوكن عبر CREATE2. استخدم مساعد الـ API generate-salt قبل كل إطلاق؛ فهو يبحث مقابل قالب التوكن الحالي على السلسلة ويُرجع كلًّا من ملح فريد وعنوان التوكن المتوقّع. العنوان المُرجَع ينتهي بـ 6666. مرّر الـ salt المُرجَع دون تغيير إلى دالة الإنشاء واستخدم الـ address المُرجَع لمعاينة ما قبل المعاملة أو للتحقق بعد المعاملة.

مرجع الأخطاء​

رسائل الفشل (revert) الأكثر احتمالًا لمصادفتها، مجمّعة حسب الاستدعاء.

الإنشاء

الرسالةالسبب
Config not found / Config not activeconfigId غير صحيح أو معطَّل
Invalid lock durationlockDuration ليست 0 وخارج النافذة المسموح بها
Invalid total supplyمجموع توكنات البيع المسبق والسيولة في القالب لا يساوي 1e9
Insufficient creation feemsg.value أقل من رسوم الإنشاء التي تفرضها المنصة
Buy tax exceeds max / Sell tax exceeds maxجانب ضريبي أعلى من 1000 BPS
Tax must be > 0كلا جانبي الضريبة يساويان صفرًا
Tax duration required / Tax duration too shortالمدة صفرية أو أقصر من antiFarmerDuration
Invalid allocationحصص توزيع الضريبة لا تساوي مجموعها 10000
Fee receiver requiredمسار مستلم-المحفظة مع feeReceiver يساوي صفرًا
Config not bound to this quotetaxConfig.quoteToken لا يطابق ارتباط القالب
Dex not enableddexKey ليس مدخل DEX مُفعَّلًا

المساهمة

الرسالةالسبب
Invalid fund managerالعنوان ليس مدير أموال (fundManager) لـ microsale
Quote sale: use contributeMicroSaleQuoteاستدعاء أصلي (native) على بيع بعملة ERC20
Native sale: use contributeMicroSaleاستدعاء ERC20 على بيع بعملة أصلية
MicroSale not activeالبيع مُنهى أو مُلغى
Contribution outside of start and end timeقبل البداية أو بعد النهاية
Buying amount exceeds hard capسيدفع totalRaised فوق السقف
Contribute more than allowedيتجاوز maxContribution الخاص بهذا البيع
Contribution too smallيُقرَّب إلى صفر توكن
Non-standard quote transferتوكن تسعير ذو ضريبة على التحويل

الإنهاء / المطالبة / السحب

الرسالةالسبب
Unauthorizedليس مالك البيع ولا مشغّل منصة
Hard cap not reachedالإنهاء قبل امتلاء السقف بالضبط
MicroSale not finalizedالمطالبة قبل الإنهاء
Nothing to claim / Already claimedمطالبة بلا مخصصات، أو مطالبة مرتين
Hard cap reachedسحب كامل تمت محاولته على بيع امتلأ فعلًا
Pool is still in progressسحب كامل قبل انتهاء البيع
Hard cap already reachedسحب طارئ بعد امتلاء السقف
Too close to end timeسحب طارئ ضمن آخر 15 دقيقة
No contributionسحب بلا أي مساهمة