مرجع قراردادها
این صفحه مرجع مهندسی اجزای آنچین پشته غیرامانی است. آدرسها و گزارشهای حسابرسی با انتشار هر فاز، برای هر زنجیره در ادامه منتشر میشوند.
قواعد آدرس (EVM)
هر چهار قرارداد EVM یک deployer مشترک دارند (یک deployer قطعی CREATE2، مثلاً 0x4e59b44847b379578588920cA78FbF26c0B4956C) و برای هر نسخه هش init code یکسانی دارند، بنابراین آدرس factory و هاب روی همه زنجیرههای 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): تابع کمکی برای keeperها.
رویدادها
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)
سولانا: برنامه 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,
}
seedهای 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 }
سولانا: برنامه 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): عمومی؛ ساعت، سقف و اختیار delegate را بررسی میکند و سپس بهعنوان delegate با CPI transfer_checkedرا اجرا میکند.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
بیتکوین: مولتیسیگ P2WSH برای هر لینک
الگوی descriptor
wsh(multi(2, <merchant_pubkey>, <platform_pubkey>))
معادل taproot (نسخه ۲، پس از بلوغ ابزارهای MuSig2):
tr(<NUMS>, multi_a(2, <merchant_pubkey>, <platform_pubkey>))
اشتقاق
- کلید پذیرنده: از xpub ثبتشده پذیرنده هنگام ثبتنام مشتق میشود، یک index برای هر لینک پرداخت.
- کلید پلتفرم: از xpub مربوط به HSM پلتفرم مشتق میشود، یک index برای هر لینک پرداخت.
PSBT بازپرداخت
در زمان واریز، یک PSBT امضانشده ساخته میشود که مبلغ واریز منهای کارمزد را به پرداختکننده برمیگرداند. هر دو امضاکننده بلافاصله آن را امضا میکنند؛ نتیجه رمزنگاریشده ذخیره میشود و هر زمان بدون امضای دیگری قابل انتشار است.
گزارشهای حسابرسی
با تکمیل هر حسابرسی اینجا منتشر میشوند. هر مورد شامل: شرکت حسابرسی، محدوده، commit، تاریخ، لینک گزارش و commit رفع اشکال.
(گزارشها با انتشار فازها اضافه میشوند.)