Program DvP adalah program standar untuk delivery versus payment di Solana,
dikelola oleh Solana Foundation dan diaudit oleh Cantina. Dua pihak menyepakati
sebuah trade, masing-masing mengirim sisinya (leg) ke akun escrow melalui
transfer token biasa, lalu otoritas penyelesaian menyelesaikan kedua sisi dalam satu transaksi, sehingga
keduanya berpindah atau tidak sama sekali. Otoritas penyelesaian adalah alamat ketiga
yang disebutkan dalam trade, seperti venue atau agen yang mengaturnya. Tidak ada pihak yang
perlu menulis atau men-deploy program, dan wallet atau kustodian yang dapat mengirim transfer
token standar (TransferChecked) dapat mendanai sebuah leg tanpa integrasi
khusus DvP. Sebelum penyelesaian, masing-masing pihak dapat menarik kembali legnya sendiri atau membatalkan
trade.
Baca catatan sebelum bertindak berdasarkan catatan tersebut
Pembuatan catatan trade bersifat permissionless, sehingga sebuah catatan bukan bukti kesepakatan. Setiap pihak membaca ketentuan yang tersimpan sebelum mendanai, dan otoritas penyelesaian membacanya sebelum menyelesaikan (lihat verifikasi).
Cara kerjanya
Setiap trade mendapatkan satu catatan milik program dan dua akun escrow, satu per leg. Pihak
asset-leg (user_a) dan pihak cash-leg (user_b) masing-masing mendanai satu leg dengan
mentransfer token ke akun escrow untuk leg tersebut. Otoritas penyelesaian
adalah satu-satunya penanda tangan yang dapat menyelesaikan. Penyelesaian mentransfer jumlah
yang disepakati dari setiap leg ke pihak lawan, mengembalikan kelebihan apa pun kepada pihak yang memiliki
leg tersebut, dan menutup catatan beserta kedua escrow. Sifat atomik berasal dari
transaksi Solana: kedua transfer berada dalam satu transaksi,
sehingga keduanya berlaku atau tidak sama sekali.
Setiap refund, penarikan kembali, dan pengembalian kelebihan masuk ke associated
token account milik pihak tersebut: akun user_a untuk mint_a, akun user_b untuk mint_b. Sistem
kustodian atau treasury dapat mendanai sebuah leg dari akunnya sendiri, tetapi apa pun yang
dikembalikan masuk ke akun pihak tersebut, bukan kembali ke kustodian. Setiap trade
juga meninggalkan akun penanda permanen (lihat State).
Panduan
Halaman langkah membahas satu trade dari pembuatan hingga penyelesaian, dengan TypeScript dan Rust untuk setiap instruksi.
Buat trade
Instal klien dan catat ketentuan trade dengan CreateDvp
Danai leg
Verifikasi ketentuan yang tersimpan, lalu danai setiap leg dengan transfer biasa
Selesaikan trade
Selesaikan kedua leg dalam satu transaksi sebagai otoritas penyelesaian
Batalkan trade
Tarik kembali sebuah leg, batalkan atau tolak trade, dan pulihkan deposit yang terlambat
Sebuah demo devnet menjalankan trade dari awal hingga akhir: membuat trade, mendanai kedua escrow dengan transfer token standar, dan menyelesaikan kedua leg dalam satu transaksi.
Memilih antara program dan delegasi
Delivery vs Payment (DvP) menggunakan delegasi menyelesaikan pertukaran yang sama tanpa program: masing-masing pihak mendelegasikan posisinya ke agen penyelesaian, yang memindahkan kedua leg dalam satu transaksi.
- Program tidak memerlukan delegasi, sehingga batas satu delegate per token account tidak berlaku, dan otoritas penyelesaian tidak dapat mengalihkan hasil. Setiap trade bergantung pada program yang dapat di-upgrade dan upgrade authority-nya.
- Pola delegasi tidak memiliki dependensi program dan bekerja dengan mint yang
memiliki Scaled UI Amount. Program menolak mint tersebut, yang berarti mengecualikan setiap
mint yang dibuat dari template
tokenized-securitymilik Mosaic (lihat batasan konfigurasi mint).
Peran
Program ini bersifat simetris. Dalam antarmukanya, kedua pihak adalah user_a, yang
mengirimkan mint_a, dan user_b, yang mengirimkan mint_b. README dan klien yang dihasilkan
menyebut mint_a sebagai asset leg dan mint_b sebagai cash leg, dan
halaman ini mengikuti konvensi tersebut, tetapi tidak ada ketentuan dalam program yang mengharuskan cash
leg berupa instrumen kas. Dua aset, atau dua stablecoin, diselesaikan dengan cara yang sama.
| Peran | Siapa | Menandatangani | Catatan |
|---|---|---|---|
| Pihak asset-leg | user_a, mengirimkan mint_a | Transfer pendanaannya sendiri; Reclaim, Reject, Recover | Wallet keypair, atau smart wallet berbasis PDA seperti vault multisig. Akun multisig SPL Token atau program account tidak dapat menjadi pihak: Create gagal dengan PartyNotSignerCapable |
| Pihak cash-leg | user_b, mengirimkan mint_b | Transfer pendanaannya sendiri; Reclaim, Reject, Recover | Persyaratan yang sama |
| Otoritas penyelesaian | Alamat ketiga yang disebutkan saat pembuatan | Settle, Cancel | Satu-satunya penanda tangan yang dapat menyelesaikan. Tidak dapat mengalihkan hasil, yang ditetapkan saat pembuatan. Menerima rent dari akun yang ditutup saat menyelesaikan atau membatalkan |
| Pembayar rent | Siapa pun yang menandatangani CreateDvp | Create | Mendanai rent (deposit SOL yang menjaga akun tetap terbuka) untuk catatan, nonce tombstone, dan kedua escrow. Tidak dicatat sebagai penerima rent: rent dari akun yang ditutup diberikan kepada siapa pun yang menutup trade |
ID Program
dvp34bdbcEm4f4FCUjGV4mDAkDshaQR4LkK8fdcsyZq
| Cluster | Program | Upgrade authority | Slot deploy terakhir |
|---|---|---|---|
| mainnet-beta | dvp34bdbcEm4f4FCUjGV4mDAkDshaQR4LkK8fdcsyZq | DXtFpbPjcn2hxPnw79x1Pfoj35vXh5AsWBkS37YnXMVv | 452,058,374 |
| devnet | dvp34bdbcEm4f4FCUjGV4mDAkDshaQR4LkK8fdcsyZq | 5EX1zFeJWj4rGYZv432WnYw8CbaSUeTdxPx4r573UgYU | 479,376,863 |
Program ini dapat di-upgrade di kedua cluster. Angka di atas adalah yang dilaporkan
solana program show pada 2 Oktober 2026; jalankan perintah yang sama untuk
mendapatkan nilai terkini. Build devnet lebih lama daripada commit yang menjadi acuan halaman langkah
(lihat Install),
dengan kumpulan instruksi dan error yang sama.
Siklus hidup
Sebuah trade terbuka sejak CreateDvp hingga salah satu dari Settle, Cancel, atau Reject menutupnya.
Pendanaan tidak memiliki instruksi tersendiri: sebuah leg dianggap terdanai ketika akun
escrow-nya menyimpan setidaknya jumlah yang disepakati. Reclaim berlaku per leg dan membiarkan
trade tetap terbuka, sehingga masalah pada satu leg tidak memaksa pihak lain membatalkan
seluruh trade.
State
Setiap trade memiliki satu akun SwapDvp berukuran 458 byte, dimiliki oleh program. Alamatnya
diturunkan dari otoritas penyelesaian, kedua pihak, kedua
mint, dan sebuah nonce (seed
["dvp", settlement_authority, user_a, user_b, mint_a, mint_b, nonce]). Jumlah
dan waktu disimpan di dalam akun dan tidak memengaruhi alamat,
sehingga harus dibaca dan tidak boleh diasumsikan. Sebuah akun penanda kecil,
nonce tombstone di ["nonce", swap_dvp], dibuat bersama trade dan
tidak pernah ditutup, sehingga setiap kombinasi pihak, mint, otoritas, dan nonce hanya dapat
digunakan untuk satu trade.
| Field | Tipe | Arti |
|---|---|---|
bump | u8 | PDA bump |
user_a, user_b | Pubkey | Kedua pihak |
mint_a, mint_b | Pubkey | Mint untuk asset leg dan cash leg |
settlement_authority | Pubkey | Satu-satunya penanda tangan yang dapat menyelesaikan atau membatalkan |
token_program_a, token_program_b | Pubkey | token program yang memiliki setiap mint; sebuah trade dapat mencampur leg SPL Token dan Token-2022 |
amount_a, amount_b | u64 | Jumlah yang disepakati untuk setiap leg, dalam satuan terkecil mint (base unit) |
expiry_timestamp | i64 | Setelah waktu jaringan ini (jam onchain), Settle ditolak. Reclaim, Cancel, dan Reject tetap berfungsi |
nonce | u64 | Membedakan trade yang memiliki seed lain yang sama. Sekali pakai |
ref_string | [u8; 64] | Referensi klien yang opaque, diisi nol (zero-padded); program tidak pernah membacanya |
user_a_settlement_destination | Pubkey | Menerima cash leg saat Settle; secara default user_a |
user_b_settlement_destination | Pubkey | Menerima asset leg saat Settle; secara default user_b |
mint_a_authority, mint_b_authority | Pubkey | Mint authority yang dicatat saat pembuatan; Settle gagal jika salah satunya berubah |
earliest_settlement_timestamp | Option<i64> | Jika diatur, Settle ditolak sebelum waktu jaringan ini |
Daftar field diambil dari IDL program pada commit yang disebutkan di bawah Buat trade.
Instruksi
| Instruksi | Penanda tangan | Efek |
|---|---|---|
CreateDvp | Pembayar mana pun | Membuat catatan SwapDvp, nonce tombstone-nya, dan kedua akun escrow. Tidak memindahkan token |
ReclaimDvp | user_a atau user_b | Mengembalikan leg milik penanda tangan dari escrow. Trade tetap terbuka dan leg dapat didanai kembali |
SettleDvp | Otoritas penyelesaian | Mentransfer amount_a ke tujuan user_b dan amount_b ke tujuan user_a, mengembalikan kelebihan apa pun kepada pihak pemilik leg, menutup catatan dan kedua escrow |
CancelDvp | Otoritas penyelesaian | Me-refund isi escrow A ke user_a dan escrow B ke user_b, menutup catatan dan kedua escrow |
RejectDvp | user_a atau user_b | Efek sama seperti Cancel, ditandatangani oleh salah satu pihak |
RecoverDvp | user_a atau user_b | Setelah trade ditutup: menguras escrow yang dibuat ulang ke token account milik penanda tangan dan menutupnya. Mencakup deposit yang masuk setelah Settle, Cancel, atau Reject |
Setiap refund masuk ke associated token account milik pihak tersebut untuk mint leg itu, siapa pun yang mendanai escrow.
Akun dan argumen setiap instruksi tersedia di halaman untuk langkah tersebut.
Error
| Kode | Error | Kapan |
|---|---|---|
| 0 | SignerNotParty | Reclaim, Reject, atau Recover ditandatangani oleh alamat yang bukan user_a atau user_b |
| 1 | DvpExpired | Settle setelah expiry_timestamp |
| 2 | SettlementAuthorityMismatch | Settle atau Cancel ditandatangani oleh alamat selain otoritas penyelesaian |
| 3 | SettlementTooEarly | Settle sebelum earliest_settlement_timestamp |
| 4 | LegNotFunded | Settle saat sebuah escrow menyimpan kurang dari jumlah yang disepakati |
| 5 | ExpiryNotInFuture | Create dengan expiry pada atau sebelum waktu jaringan saat ini |
| 6 | EarliestAfterExpiry | Create dengan waktu penyelesaian paling awal setelah expiry |
| 7 | SelfDvp | Create dengan user_a sama dengan user_b |
| 8 | SameMint | Create dengan mint_a sama dengan mint_b |
| 9 | ZeroAmount | Create dengan jumlah nol pada salah satu leg |
| 10 | BlockedMintExtension | Create atau Settle dengan mint yang memiliki TransferFee, InterestBearing, ScaledUiAmount, atau NonTransferable |
| 11 | SettlementAuthorityIsParty | Create dengan otoritas penyelesaian yang sama dengan salah satu pihak |
| 12 | SettlementAuthorityExecutable | Create dengan otoritas penyelesaian yang executable |
| 13 | NonceAlreadyUsed | Create yang menggunakan kembali (seeds, nonce) yang sudah memiliki tombstone |
| 14 | ExpiryTooFarInFuture | Create dengan expiry lebih dari satu tahun ke depan |
| 15 | RefStringTooLong | Create dengan referensi lebih panjang dari 64 byte |
| 16 | DvpStillOpen | Recover saat trade masih terbuka; gunakan Reclaim |
| 17 | DvpNeverCreated | Recover dengan seed yang tidak memiliki tombstone |
| 18 | EscrowPreloadedWithLamports | Create saat escrow non-native menyimpan lamport di atas minimum rent-exempt-nya |
| 19 | SettlementDestinationIsSwapDvp | Create dengan tujuan settlement yang sama dengan catatan trade |
| 20 | SwapDvpPreloadedWithLamports | Create saat alamat catatan menyimpan lamport di atas cadangan rent-nya |
| 21 | RecipientAtaMismatch | Sebuah token account penerima atau refund tidak lagi dimiliki oleh wallet dan mint yang diharapkan |
| 22 | PartyNotSignerCapable | Create dengan party yang bukan akun milik sistem dan non-executable |
| 23 | MintAuthorityChanged | Settle saat mint authority suatu leg berbeda dari nilai yang dicatat saat pembuatan |
Event dan indexing
Program ini tidak mengeluarkan event onchain. Indexer atau sistem rekonsiliasi membaca
status akun SwapDvp dan saldo token dari kedua escrow, serta menggunakan
ref_string untuk mengorelasikan trade dengan order off-chain-nya. Karena catatan
ditutup saat settlement, sistem yang membutuhkan ketentuan tersebut setelahnya
menyimpannya saat membacanya, atau merekonstruksinya dari transaksi yang membuat
trade tersebut.
Token yang didukung
Sebuah trade dapat memasangkan leg SPL Token dengan leg Token-2022; setiap leg membawa token program-nya sendiri. Leg Wrapped SOL didukung.
| Ekstensi Token-2022 pada mint sebuah leg | Perilaku program |
|---|---|
| TransferFee, InterestBearing, ScaledUiAmount, NonTransferable | Ditolak saat Create dan Settle dengan BlockedMintExtension |
| PermanentDelegate, Pausable, DefaultAccountState, freeze authority, MintCloseAuthority | Diterima; setiap authority dapat bertindak atas token yang di-escrow |
| ConfidentialTransfer | Diterima; jumlah pada leg tersebut bersifat publik |
| TransferHook | Didukung, hingga 32 akun tambahan per leg |
| MemoTransfer pada akun tujuan atau refund | Diterima; program mengeluarkan memo yang diperlukan sebelum transfer |
Biaya transfer akan membuat sisi penerima kekurangan dari jumlah yang disepakati. Interest Bearing dan Scaled UI Amount tidak mengubah jumlah mentah, tetapi rate atau multiplier-nya dapat berubah antara pembuatan dan settlement trade, yang mengubah cara jumlah yang disepakati ditampilkan. NonTransferable akan membuat kedua leg terjebak.
Authority yang diterima dapat memindahkan, membekukan, atau menghentikan token yang di-escrow selama masa berlaku trade (lihat di bawah). Escrow tidak dapat dikonfigurasi untuk menerima transfer rahasia (confidential), sehingga jumlah yang di-escrow dan di-settle pada leg confidential bersifat publik.
Untuk mint dengan hook, klien me-resolve akun tambahan milik hook dan menambahkannya ke Settle, Cancel, Reject, Reclaim, dan Recover. Batas 32 per leg menghitung program hook dan akun validasinya. Jika hook authority memperbesar daftar akun hook melebihi batas tersebut, setiap transfer pada leg itu gagal, termasuk Reclaim, Cancel, Reject, dan Recover, sampai authority membatalkannya. Batas akun transaksi dapat tercapai lebih dulu sebelum batas per leg jika kedua leg memiliki hook.
Ketika akun tujuan atau refund mewajibkan memo, program memanggil program Memo
sebelum transfer, itulah sebabnya setiap instruksi yang memindahkan token
keluar dari escrow membutuhkan akun memo_program.
Batasan konfigurasi mint
Scaled UI Amount. Template tokenized-security di
Mosaic, toolkit penerbitan Solana Foundation, selalu menambahkan Scaled UI Amount, sehingga program ini tidak menerima
mint yang dibuat dari template tersebut sebagai leg. Mint yang ditujukan untuk program ini dapat
dibuat tanpa ekstensi tersebut (lihat
Token Extensions);
DvP menggunakan delegasi melakukan settlement melalui
otoritas yang didelegasikan dan tidak menerapkan pemeriksaan ini.
Mint yang dibekukan secara default. Escrow setiap trade adalah associated token account yang dimiliki oleh Program Derived Address yang baru untuk trade tersebut. Pada mint dengan Default Account State yang diatur ke frozen, escrow dibuat dalam keadaan frozen, dan transfer pendanaan ke dalamnya gagal sampai di-thaw. Di bawah Token ACL itu berarti penerbit atau transfer agent-nya mengizinkan escrow trade sebelum pendanaan: baik dengan menambahkan alamat catatan trade (pemilik escrow) ke allowlist, sehingga siapa pun dapat men-thaw escrow tersebut jika konfigurasi Token ACL mint mengaktifkan permissionless thaw, atau dengan meminta freeze authority men-thaw-nya secara langsung. Escrow yang dibekukan juga memblokir Settle, Reclaim, Cancel, Reject, dan Recover pada leg tersebut, sehingga freeze authority, dan pada mint dengan hook, hook authority, merupakan pihak tepercaya selama masa berlaku trade. Jalur escrow yang dibekukan dijelaskan di sini dan tidak dijalankan dalam snippet devnet.
Batasan
- Tidak ada pencocokan, penemuan harga, atau order book. Para pihak menyepakati ketentuan di luar ledger dan salah satunya mencatatnya.
- Tidak ada netting, dan hanya bilateral: satu catatan adalah satu trade antara dua pihak.
- Tidak ada partial fill. Settle memindahkan tepat jumlah yang disepakati dari setiap leg dan mengembalikan kelebihan apa pun kepada party leg tersebut.
- Tidak ada leg off-ledger. Kedua leg adalah token account di Solana; leg tunai pada rel yang sudah ada diselesaikan secara terpisah dan direkonsiliasi.
- Tidak ada pemeriksaan kelayakan, allowlist, atau KYC. Kontrol milik mint sendiri yang menegakkan kelayakan pemegang.
- Tidak ada settlement otomatis. Settlement authority harus menandatangani.
- Tidak ada event, dan tidak ada biaya protokol selain biaya transaksi dan rent.
Program ini menghilangkan risiko pokok (principal risk) antara kedua pihak: tidak ada leg yang bergerak kecuali keduanya bergerak. Program ini tidak menghilangkan risiko kredit penerbit atau risiko penebusan pada kedua token, kemampuan freeze, pause, atau permanent delegate authority suatu mint untuk bertindak atas token yang di-escrow (lihat token yang didukung), atau ketergantungan pada ketersediaan settlement authority untuk menandatangani.
Verifikasi sebelum pendanaan dan settlement
CreateDvp bersifat permissionless: hanya payer yang menandatangani, sedangkan para pihak dan
settlement authority tidak. Karena itu, siapa pun dapat membuat catatan yang menyebut pihak dan
ketentuan apa pun. Sebelum pendanaan, dan lagi sebelum settlement, baca akun
SwapDvp dan pastikan:
- Akun dimiliki oleh program DvP dan berukuran tepat 458 byte. Akun yang tidak dimiliki oleh program dapat diisi dengan byte yang ter-decode seperti catatan asli.
user_a,user_b,mint_a,mint_b, dansettlement_authoritysesuai dengan trade yang disepakati.amount_a,amount_b,expiry_timestamp, danearliest_settlement_timestampsesuai dengan ketentuan yang disepakati.- Kedua tujuan settlement adalah alamat yang disepakati. Catatan palsu dapat mengalihkan hasilnya.
Danai leg mencantumkan checked reader dari klien yang dihasilkan dan menunjukkan pemeriksaannya dalam kode.
Anggap sebuah trade telah selesai (settled) ketika transaksi Settle mencapai
finalized. Itu adalah tingkat
commitment jaringan; apakah itu juga menandai finalitas settlement untuk tujuan hukum
bergantung pada perjanjian para pihak dan rezim yang berlaku.
Pembuatan versi
Akun SwapDvp tidak memiliki field versi. Tata letaknya tetap pada 458 byte
(SwapDvp::LEN), dan checked reader menolak akun dengan panjang lain.
IDL memiliki versinya sendiri, 0.1.0 per 2 Oktober 2026.
Program ini dapat di-upgrade di kedua cluster (lihat Program ID). Catatan trade hanya ada sampai di-settle, dibatalkan, atau ditolak, jadi periksa repositori untuk mengetahui bagaimana upgrade memperlakukan trade yang masih terbuka, dan buat ulang klien dari IDL build yang di-deploy.
Repositori dan audit
Source, IDL, klien yang dihasilkan, dan pengujian ada di
solana-foundation/dvp di bawah lisensi
MIT. Program ini adalah program Pinocchio no_std; klien
dihasilkan dari IDL dengan Codama. Laporan kerentanan disampaikan melalui tautan
security advisory repositori, sesuai SECURITY.md-nya.
Program ini telah diaudit oleh Cantina.
Terkait
- Delivery vs Payment (DvP) menggunakan delegasi: pola delegasi tanpa program
- Token ACL: bagaimana mint yang dibatasi berinteraksi dengan akun escrow
Is this page helpful?