Vaults
يجمع التوكن الضريبي حصة من كل عملية شراء وبيع. تذهب تلك الحصة إلى مستلم رسوم (fee receiver). في إطلاق التوكن الضريبي العادي يكون مستلم الرسوم محفظة. في إطلاق vault يكون مستلم الرسوم عقدًا يُنشر عند الإطلاق، فتصل الإيرادات إلى مكان له قواعد: تقسيمها عبر محافظ، أو تدفقها إلى مستلم واحد، أو حجزها لهوية، أو أي شيء آخر يبرمجه مؤلف الـ vault.
هذه الصفحة موجّهة للمُكامِلين الذين يريدون الإطلاق بـ vault أو قراءة واحد. إذا كنت تريد كتابة vault خاص بك، راجع custom-vault.md.
المحتويات
- كيف تصل الإيرادات إلى vault
- الإطلاق بـ vault
- الإيرادات الأصلية مقابل ERC20
- الـ vaults التي تقدّمها CheesePad
- قراءة vault بشكل عام
- عناوين المصانع
كيف تصل الإيرادات إلى vault
trader ──buy/sell──▶ tax token
│ collects tax on the transfer
▼
settles the tax ← permissionless; anyone can poke it
│ splits by the allocation you set at launch
┌──────────────┼───────────────┬───────────────┐
▼ ▼ ▼ ▼
fee receiver holders burn liquidity
(the vault) (dividends) (0xdead) (adds LP)
لا يدفع التوكن الإيرادات في كل صفقة. بل يتراكم عليه الضريبة ويسوّيها على دفعات. عندما يسوّي، تُرسَل
حصة مستلم الرسوم إلى الـ vault. يسجّل الـ vault الخاص بك الإيرادات ويدفعها لاحقًا، عبر استدعاءات
distribute() / claim() الخاصة به. هذا التجميع على دفعات هو سبب أن الـ vault يأخذ دائمًا شكل
"تراكَم الآن، ادفع لاحقًا".
رسوم المنصة البالغة 10% على ضريبة المُنشئ في CheesePad هي رسم منفصل، وليست جزءًا من allocation
الخاصة بك؛ راجع نموذج رسوم التوكن لكيفية ملاءمتها إلى جانب الضريبة.
تأتي حصص allocation الأربع من allocation التي تحددها في taxConfig عند الإطلاق، ويجب أن يساوي
مجموعها 10000 BPS:
| Slice | إلى أين تذهب |
|---|---|
feeReceiver | الـ vault |
holders | حائزو التوكن، كأرباح (تحتاج minHolderShare غير صفرية) |
burn | العنوان الميت |
liquidity | تُضاف مرة أخرى كسيولة LP |
حتى يتلقى الـ vault أي دفعة، يجب أن تكون allocation.feeReceiver أعلى من صفر، وأن يكون جانب ضريبة
واحد على الأقل غير صفري. يتحقق الـ launchpad من ذلك ويفشل الإطلاق خلاف ذلك.
الإطلاق بـ vault
استخدم createMicroSaleTaxTokenWithVaultV2. فوق CreateParamsV2 المعتادة، تمرّر عنوان مصنع vault،
وكتلة vaultData مُرمَّزة بـ ABI تضبط الـ vault المحدد، وdexKey الذي يسمّي الـ DEX المُراد
الإدراج عليه.
function createMicroSaleTaxTokenWithVaultV2(
CreateParamsV2 calldata params, // same struct as the tax-token launch, incl. taxConfig
address vaultFactory, // a factory the platform trusts (see Factory addresses)
bytes calldata vaultData, // ABI-encoded config for this vault; shape depends on factory
address dexKey // the DEX to list on
) external payable returns (address fundManager);
ما يقوم به الـ launchpad، بالترتيب، وكلها بمبدأ الفشل الآمن (أي فشل يُلغي الإطلاق بأكمله):
- يؤكّد أن المصنع يشير إلى هذا الـ launchpad.
- يؤكّد أن المصنع يقبل توكن التسعير الخاص بالبيع.
- يؤكّد أن المصنع يفهم مراجعة بيانات الإطلاق الحالية.
- يستدعي دالة مراجعة المصنع مع معاملات إطلاقك؛ ويجب أن توافق.
- يجعل المصنع ينشر الـ vault.
- يؤكّد أن وضع إيرادات الـ vault يطابق توكن التسعير (راجع أدناه).
- يربط الـ vault كمستلم رسوم التوكن.
أنت لا توصّل أي شيء بنفسك أبدًا. إذا وافق المصنع، تحصل على توكن حيّ تتدفق ضريبته إلى vault جديد.
نفس التواصل يدعم توكن bonding curve ضريبي: createBondingCurveTaxTokenWithVaultV2 تأخذ
vaultFactory وvaultData وdexKey وتجري الفحوص المتطابقة. القيد هو أن وضع إيرادات الـ vault يجب
أن يطابق عملة تسعير المنحنى — الوضع الأصلي لمنحنى BNB، ووضع ERC20 لمنحنى مُسعَّر بـ ERC20 (راجع
الإيرادات الأصلية مقابل ERC20). كل ما يلي ينطبق على نمطي الإطلاق كليهما.
ترميز vaultData
vaultData معتمة بالنسبة للـ launchpad؛ كل مصنع يعرّف شكله الخاص. يعلن المصنع عن ذلك الشكل عبر
vaultDataSchema()، حتى تتمكن واجهة المستخدم من بناء النموذج بشكل عام. للترميز يدويًا، اتبع ترتيب
حقول المخطط وأنواعها. أمثلة ملموسة للـ vaultين المُقدَّمين موجودة أدناه.
استعادة عنوان الـ vault
بعد الإطلاق، اقرأه من البيع:
const sale = await launchpad.getMicroSaleByFundManager(fundManager);
console.log("vault:", sale.vault); // the deployed vault
console.log("via factory:", sale.vaultFactory); // the factory that produced it
يسجّل البيع أيضًا أي مصنع أنتج الـ vault، فيمكن لقائمة سماح خارج السلسلة أن تضع شارة على الـ vaults التي جاءت من مصنع موثوق.
الإيرادات الأصلية مقابل ERC20
يتعامل الـ vault مع الإيرادات بأصل واحد بالضبط، يُقرَّر عند الإطلاق:
- الوضع الأصلي عندما يكون توكن التسعير الخاص بالبيع هو WBNB. تصل الإيرادات كـ BNB.
- وضع ERC20 خلاف ذلك. تصل الإيرادات كتوكن التسعير، وتُرفض العملات الأصلية العابرة.
يؤكّد الـ launchpad أن وضع الـ vault يطابق توكن التسعير، فلا يمكن لمصنع غير متطابق أن يعطّل التداول. لإطلاق بعملة تسعير ERC20، يجمع المساهمون التمويل بتوكن التسعير ERC20 ذاك — راجع microsale.md. يأتي توكن التسعير من ارتباط القالب، لذا فإن إطلاقًا بمستلم-محفظة أو بلا ضريبة مقابل قالب مرتبط بـ ERC20 يجمع التمويل بتوكن التسعير ذاك كذلك؛ الفرق مع vault هو فقط في المكان الذي تصل إليه حصة مستلم الرسوم.
الـ vaults التي تقدّمها CheesePad
vaultان جاهزان، لكلٍّ منهما مصنعه الخاص. توجّه createMicroSaleTaxTokenWithVaultV2 إلى المصنع
وتمرّر vaultData المطابق.
SplitterVault: مستفيدون ثابتون حسب الحصة
يقسّم الإيرادات عبر قائمة ثابتة من المحافظ بنقاط الأساس. حتى 50 مستفيدًا، ويجب أن يساوي مجموع الحصص 10000، بلا تكرار، وبلا عناوين صفرية.
vaultData هي abi.encode(address[] payees, uint16[] bps):
const payees = ["0xAaa...", "0xBbb..."];
const bps = [7000, 3000]; // 70% / 30%; must sum to 10000
const vaultData = ethers.AbiCoder.defaultAbiCoder().encode(
["address[]", "uint16[]"],
[payees, bps]
);
await launchpadRW.createMicroSaleTaxTokenWithVaultV2(params, SPLITTER_FACTORY, vaultData, dexKey, {
value: creationFee,
});
استخدام الـ vault بعد الإطلاق:
distribute()مفتوحة بلا إذن. تُقيّد حصة كل مستفيد من الرصيد المتراكم وتدفعها إليه. إذا تعذّر على مستفيد الاستلام (عقد يفشل تنفيذه، مثلًا)، تُحفظ حصته كـowedليسحبها لاحقًا، ويظل الآخرون يتقاضون.claim()تتيح للمستفيد سحب رصيدهowedالخاص.splitConfig()تُرجع المستفيدين وحصصهم بنقاط الأساس؛ وowed(address)تُرجع الرصيد المعلّق لمستفيد؛ وcredited()تُرجع الإجمالي الجاري المُقيَّد.
يقبل SplitterVault أي توكن تسعير.
GiftVault: التدفق إلى المحفظة خلف حساب X
يحتفظ بإيرادات توكن للشخص خلف حساب X (تويتر). لا يُدفع لأحد حتى تُربط محفظة بالحساب، والربط مُصرَّح به بواسطة توقيع مُرحِّل (relayer) من المنصة، فلا يمكن إلا للمالك الحقيقي للحساب أن يطالب.
vaultData هي abi.encode(string xHandle, uint256 timeoutPeriod):
const vaultData = ethers.AbiCoder.defaultAbiCoder().encode(
["string", "uint256"],
["cheesepad", 30n * 24n * 60n * 60n] // handle, and 30-day bind window
);
await launchpadRW.createMicroSaleTaxTokenWithVaultV2(params, GIFT_FACTORY, vaultData, dexKey, {
value: creationFee,
});
timeoutPeriod بين يوم واحد و365 يومًا. يتطلب مصنع GiftVault أيضًا أن تكون allocation.holders أعلى
من صفر، بسبب الحل الاحتياطي أدناه.
كيف تسير الأمور:
- الربط. يحصل مالك المحفظة على إثبات موقّع من المُرحِّل (توقيع EIP-712 على الحساب، والتوكن،
ومحفظة المستفيد، وnonce، وتاريخ انتهاء) ويستدعي
bindBeneficiary(beneficiary, nonce, validUntil, signature). من تلك اللحظة، تتدفق الإيرادات إلى تلك المحفظة. يكون الربط مفتوحًا فقط حتى انتهاء المهلة، وفقط عندما يتحقق الإثبات. - السحب. بعد الربط، تدفع
distribute()الإيرادات المتراكمة إلى المستفيد، وتتيح لهclaim()سحبها. - القفل. يمكن للمستفيد استدعاء
lock()لإقصاء المُرحِّل والمنصة عن أي إعادة ربط مستقبلية. - الإنقاذ. قبل انتهاء المهلة وقبل القفل، يمكن لدعامة المنصة الاحتياطية تصحيح محفظة مربوطة خطأً. وهي لا تعيد توجيه إلا الإيرادات المستقبلية.
- الحل الاحتياطي بالأرباح. إذا لم يربط أحد قبل انتهاء المهلة، يمكن لأي شخص استدعاء
distributeDividend()، التي توجّه الإيرادات غير المُطالَب بها إلى حائزي التوكن كأرباح. لهذا يصرّ المصنع على حصة حائزين. بمجرد إطلاقها، يبقى الـ vault بشكل دائم في وضع الأرباح ويُغلَق الربط.
قراءة vault بشكل عام
يصف كل vault حقول قراءته وإجراءاته الخاصة عبر vaultUISchema(). يمكن لواجهة مستخدم عرض vault لم
ترَه من قبل: تقرأ المخطط، وتستدعي كل دالة قراءة، وتفك ترميز النتيجة باستخدام الأنواع المُعلَنة.
الشكل المشترك:
const vault = new ethers.Contract(sale.vault, VaultABI, provider);
const isNative = await vault.isNativeRevenue(); // true = BNB, false = ERC20
const quote = await vault.quoteToken(); // revenue asset
const desc = await vault.description(); // one-liner for listings
const schema = await vault.vaultUISchema(); // methods to render (reads + writes)
تُرجع vaultUISchema() قيمة vaultType، وdescription، وقائمة من الدوال. كل دالة إما حقل قراءة
(تستدعيها واجهة المستخدم وتعرض النتيجة المُصنَّفة) أو إجراء كتابة (تعرض واجهة المستخدم زرًا ونموذج
إدخال، بالإضافة إلى أي موافقات ERC20 تحتاجها أولًا). أنواع المخطط مشروحة في
custom-vault.md وevents-and-data.md.
الجزء المهم لقارئ عام: لا يكشف الـ vault إلا ما يعلنه مخططه. لا يوجد استبطان تلقائي للتخزين، لذا ثق بالمخطط بوصفه قائمة كل ما يستحق العرض.
عناوين المصانع
| Vault | Network | Factory |
|---|---|---|
| SplitterVault | BNB (56) | 0x9d04B0Bfe281411d4A01a69BD89f7Ba6b7F5A59b |
| SplitterVault | BNB testnet (97) | 0xbB5165684832a8Cda1121081EBb168ca6636abc6 |
| SplitterVault | Robinhood (4663) | 0x58DBab8C3529492c12Ee913313Cf600f522a39D9 |
| GiftVault | BNB (56) | 0xFa36D3e2240BEDB22bad35D8FD4165AAf0598896 |
| GiftVault | BNB testnet (97) | 0x8227F4330E3aa43c94b9fDc409D71A6C6C2033B7 |
| GiftVault | Robinhood (4663) | 0x7FD34AeA57250aC66C59448339316aF745f6B9ef |
المصنع عديم الحالة وغير قابل للتغيير. الإصدار الجديد هو عنوان جديد، لذا أكّد العنوان الحالي مع فريق CheesePad قبل أتمتة الإطلاقات مقابله.