مرجع العقود
هذه الصفحة هي المرجع الهندسي للأجزاء على السلسلة في المنظومة غير الاحتجازية. تُنشر العناوين وتقارير التدقيق أدناه لكل سلسلة مع إطلاق المراحل.
اصطلاحات العناوين (EVM)
تتشارك عقود EVM الأربعة الناشر نفسه (ناشر CREATE2 حتمي، مثل 0x4e59b44847b379578588920cA78FbF26c0B4956C) وتجزئة init code نفسها لكل إصدار، لذا فإن عناوين الـ factory والـ hub هي نفسها على كل سلاسل EVM. هذا يبسّط كود العميل والتوثيق.
| السلسلة | chainId | PaymentLinkFactory | SubscriptionHub | FeeSplitter |
|---|---|---|---|---|
| Base | 8453 | يُنشر عند النشر | يُنشر عند النشر | يُنشر عند النشر |
| Ethereum | 1 | نفسه | نفسه | نفسه |
| Arbitrum One | 42161 | نفسه | نفسه | نفسه |
| Optimism | 10 | نفسه | نفسه | نفسه |
| Polygon PoS | 137 | نفسه | نفسه | نفسه |
عناوين PaymentLinkReceiver خاصة بكل رابط: factory.computeAddress(keccak256(linkId)).
EVM: PaymentLinkFactory
الدوال
computeAddress(bytes32 linkId) external view returns (address): عنوان CREATE2 حتمي. يمكن استدعاؤها قبل أي نشر.deployAndPay(bytes32 linkId, Split calldata split, address token, uint256 amount) external payable: تنشر النسخة عند أول دفعة وتحوّل الأموال.isDeployed(bytes32 linkId) external view returns (bool).setSplit(bytes32 linkId, Split calldata split) external: لا تُستدعى إلا قبل أول دفعة؛ تضبط التقسيم الثابت الذي ستُهيّأ به النسخة.pause() / unpause(): للتوقيع المتعدد فقط.
الأحداث
ReceiverDeployed(bytes32 indexed linkId, address receiver)SplitRegistered(bytes32 indexed linkId, Split split)
بنية Split
struct Split {
address merchant;
address platform;
address referral;
address bridgeFee;
uint16 platformBps;
uint16 referralBps;
uint16 bridgeFeeBps;
}
يجب أن يكون مجموع حقول bps < 10000. يذهب الباقي إلى التاجر.
EVM: PaymentLinkReceiver (نسخة مصغّرة)
الدوال
pay(address token, uint256 amount) external payable: نقطة الدخول الرئيسية.token == address(0)تعني العملة الأصلية.refund(bytes32 txId, address to, uint256 amount) external: مقصورة على EOA الـ keeper أو التوقيع المتعدد للنشر.split() external view returns (Split memory).
الأحداث
Paid(bytes32 indexed linkId, address indexed payer, address indexed token, uint256 amount, bytes32 txId)Refunded(bytes32 indexed linkId, bytes32 indexed txId, address to, uint256 amount)
حالات Revert
InvalidTokenوInvalidAmountوSplitFailedوAlreadyRefunded.
EVM: FeeSplitter
الدوال
split(Split calldata s, address token, uint256 amount) external payable: استدعاء داخلي منPaymentLinkReceiverوSubscriptionHub. لا تُستدعى مباشرة عادةً.
الأحداث
SplitExecuted(bytes32 indexed txId, address merchant, uint256 merchantAmount, address platform, uint256 platformAmount, address referral, uint256 referralAmount, address bridgeFee, uint256 bridgeFeeAmount)
EVM: SubscriptionHub
الدوال
createSubscription(bytes32 id, address payer, IERC20 token, uint256 amount, uint64 interval, uint256 cap, Split calldata split) external: تسجّل الاشتراك على السلسلة.charge(bytes32 id) external: عامة ولا تتطلب صلاحيات؛ تفرض التوقيت والحد الأقصى والـ allowance والرصيد.charge(bytes32[] ids) external: نسخة دفعية؛ يُتحقق من كل id على حدة.cancel(bytes32 id) external: يستدعيها الدافع.subscription(bytes32 id) external view returns (Subscription memory).isDue(bytes32 id) external view returns (bool): دالة مساعدة للـ keepers.
الأحداث
SubscriptionCreated(bytes32 indexed id, address indexed payer, IERC20 token, uint256 amount, uint64 interval, uint256 cap)Charged(bytes32 indexed id, uint256 amount, uint64 nextChargeAt)ChargeSkipped(bytes32 indexed id, bytes32 reason): الأسباب:NotDueوInsufficientAllowanceوInsufficientBalanceوAlreadyChargedThisPeriodوCapExceededوPaused.Canceled(bytes32 indexed id)
الثوابت التي تفرضها charge
block.timestamp >= subscription.nextChargeAtblock.timestamp > subscription.lastChargedAt(رتيب)subscription.amountCharged + subscription.amount <= subscription.captoken.allowance(subscription.payer, address(this)) >= subscription.amounttoken.balanceOf(subscription.payer) >= subscription.amount
مثال على مسار الدافع
// 1. Payer signs an allowance to the hub
await usdc.approve(subscriptionHub.address, cap)
// 2. Merchant (via OrcaRail) creates the subscription on-chain
await subscriptionHub.createSubscription(
id,
payer,
usdc,
amount,
interval,
cap,
split
)
// 3. Anyone calls charge when due
await subscriptionHub.charge(id)
Solana: برنامج payment_link
الحسابات
#[account]
pub struct PaymentLink {
pub link_id: [u8; 32],
pub expected_mint: Pubkey,
pub expected_amount: u64,
pub split: Split,
pub created_at: i64,
pub status: PaymentStatus,
}
بذور الـ PDA: [b"pl", link_id].
التعليمات
initialize(link_id, expected_mint, expected_amount, split): تهيئة مؤجّلة عند أول استخدام.pay(link_id, amount): تحويل عبر CPI من ATA الدافع إلى ATA الخاص بالـ PDA، ثم التقسيم عبر CPI.refund(link_id): مقصورة على التوقيع المتعدد.
الأحداث
PaymentReceived { link_id, payer, amount }PaymentRefunded { link_id, to, amount }
Solana: برنامج subscription
الحسابات
#[account]
pub struct Subscription {
pub id: [u8; 32],
pub payer: Pubkey,
pub mint: Pubkey,
pub amount: u64,
pub interval: i64,
pub cap: u64,
pub amount_charged: u64,
pub next_charge_at: i64,
pub last_charged_at: i64,
pub split: Split,
}
التعليمات
create(id, payer, mint, amount, interval, cap, split): تسجّل الاشتراك.charge(id): عامة؛ تتحقق من الساعة والحد الأقصى وصلاحية التفويض، ثم تنفّذtransfer_checkedعبر CPI بصفتها المفوَّض.cancel(id): للدافع فقط.
الأحداث (عبر سجلات البرنامج)
SubscriptionCreatedوCharged { amount, next_charge_at }وChargeSkipped { reason }وCanceled.
مثال على مسار الدافع
// 1. Payer approves program PDA as delegate on their USDC ATA
await token.approve(payerUsdcAta, programPda, capAmount)
// 2. create() registers the subscription PDA
// 3. charge() can be called by anyone once due
Bitcoin: توقيع متعدد P2WSH لكل رابط
قالب الـ descriptor
wsh(multi(2, <merchant_pubkey>, <platform_pubkey>))
المكافئ في taproot (الإصدار 2، بعد نضج أدوات MuSig2):
tr(<NUMS>, multi_a(2, <merchant_pubkey>, <platform_pubkey>))
الاشتقاق
- مفتاح التاجر: مشتق من xpub الذي سجّله التاجر عند التسجيل، بفهرس واحد لكل رابط دفع.
- مفتاح المنصة: مشتق من xpub الخاص بـ HSM المنصة، بفهرس واحد لكل رابط دفع.
PSBT الاسترداد
وقت الإيداع، تُجمَّع معاملة PSBT غير موقّعة تعيد مبلغ الإيداع مطروحًا منه الرسوم إلى الدافع. يوقّعها الموقّعان فورًا؛ وتُخزَّن النتيجة مشفّرة ويمكن بثها في أي وقت دون توقيع إضافي.
تقارير التدقيق
تُنشر هنا فور اكتمالها. تتضمن كل مدخلة: الجهة المدققة والنطاق والـ commit والتاريخ ورابط التقرير والـ commit الخاص بالإصلاح.
(تصل التقارير مع إطلاق المراحل.)