Delivery vs Payment (DvP)-programma

Het DvP-programma is het standaardprogramma voor delivery versus payment (levering tegen betaling) op Solana, onderhouden door de Solana Foundation en geaudit door Cantina. Twee partijen komen een trade overeen, elk stuurt zijn leg met een gewone tokenoverdracht naar een escrowaccount, en een afwikkelautoriteit wikkelt beide legs af in één transactie, zodat ofwel beide worden verplaatst, ofwel geen van beide. De afwikkelautoriteit is een derde adres dat in de trade wordt genoemd, zoals de handelsplaats of agent die de trade heeft geregeld. Geen van beide partijen schrijft of deployt een programma, en een wallet of bewaarder die een standaard tokenoverdracht (TransferChecked) kan versturen, kan een leg financieren zonder DvP-specifieke integratie. Tot de afwikkeling kan elke partij zijn eigen leg terugnemen of de trade ongedaan maken.

Lees het record voordat je erop afgaat

Het aanmaken van een traderecord vereist geen toestemming, dus een record is geen bewijs van overeenstemming. Elke partij leest de opgeslagen voorwaarden voordat ze financiert, en de afwikkelautoriteit voordat ze afwikkelt (zie verificatie).

Hoe het werkt

Elke trade krijgt een record dat eigendom is van het programma en twee escrowaccounts, één per leg. De partij van de asset-leg (user_a) en de partij van de cash-leg (user_b) financieren elk een leg door tokens over te maken naar het escrowaccount van die leg. De afwikkelautoriteit is de enige ondertekenaar die kan afwikkelen. Bij afwikkeling wordt het overeengekomen bedrag van elke leg naar de andere kant overgemaakt, wordt eventueel overschot teruggestuurd naar de partij die de leg bezit, en worden het record en beide escrows gesloten. De atomiciteit komt voort uit de transacties van Solana: beide overdrachten zitten in één transactie, dus ofwel gebeuren ze allebei, ofwel geen van beide.

Elke terugbetaling, terugvordering en overschotretour gaat naar het eigen associated token account van de partij: dat van user_a voor mint_a, dat van user_b voor mint_b. Een bewaarder of treasury-systeem kan een leg vanuit zijn eigen account financieren, maar alles wat wordt teruggestuurd komt terecht in het account van de partij, niet terug bij de bewaarder. Elke trade laat ook een permanent markeringsaccount achter (zie Status).

Handleidingen

De stappenpagina's volgen één trade van het aanmaken tot de afwikkeling, met TypeScript en Rust voor elke instructie.

Een devnet-demo doorloopt een trade van begin tot eind: de demo maakt de trade aan, financiert beide escrows met standaard tokenoverdrachten en wikkelt beide legs in één transactie af.

Kiezen tussen het programma en delegatie

Delivery vs Payment (DvP) met delegatie wikkelt dezelfde uitwisseling af zonder programma: elke kant delegeert zijn positie aan een afwikkelagent, die beide legs in één transactie verplaatst.

  • Het programma vereist geen delegatie, dus de limiet van één gedelegeerde per token account geldt niet, en de afwikkelautoriteit kan de opbrengsten niet omleiden. Elke trade is afhankelijk van een upgradebaar programma en de bijbehorende upgrade-autoriteit.
  • Het delegatiepatroon heeft geen programma-afhankelijkheid en werkt met mints die Scaled UI Amount gebruiken. Het programma weigert die mints, wat elke mint uitsluit die is gemaakt op basis van de tokenized-security-template van Mosaic (zie beperkingen voor mintconfiguratie).

Rollen

Het programma is symmetrisch. In de interface zijn de twee partijen user_a, die mint_a levert, en user_b, die mint_b levert. De README en de gegenereerde clients noemen mint_a de asset-leg en mint_b de cash-leg, en deze pagina's volgen die conventie, maar niets in het programma vereist dat de cash-leg een cashinstrument is. Twee assets, of twee stablecoins, worden op dezelfde manier afgewikkeld.

RolWieOndertekentOpmerkingen
Partij van de asset-leguser_a, levert mint_aEigen financieringsoverdracht; Reclaim, Reject, RecoverEen keypair-wallet of een PDA-gebaseerde smart wallet zoals een multisig-vault. Een SPL Token multisig-account of een program account kan geen partij zijn: Create mislukt met PartyNotSignerCapable
Partij van de cash-leguser_b, levert mint_bEigen financieringsoverdracht; Reclaim, Reject, RecoverDezelfde vereiste
AfwikkelautoriteitEen derde adres dat bij het aanmaken wordt genoemdSettle, CancelDe enige ondertekenaar die kan afwikkelen. Kan de opbrengsten, die bij het aanmaken vastliggen, niet omleiden. Ontvangt de rent van de gesloten accounts wanneer de trade wordt afgewikkeld of geannuleerd
Rent-betalerWie CreateDvp ondertekentCreateFinanciert de rent (het SOL-depot dat een account open houdt) voor het record, de nonce-tombstone en beide escrows. Niet vastgelegd als rent-ontvanger: de rent van gesloten accounts gaat naar wie de trade sluit

Program-ID

dvp34bdbcEm4f4FCUjGV4mDAkDshaQR4LkK8fdcsyZq
ClusterProgrammaUpgrade-autoriteitSlot van laatste deployment
mainnet-betadvp34bdbcEm4f4FCUjGV4mDAkDshaQR4LkK8fdcsyZqDXtFpbPjcn2hxPnw79x1Pfoj35vXh5AsWBkS37YnXMVv452,058,374
devnetdvp34bdbcEm4f4FCUjGV4mDAkDshaQR4LkK8fdcsyZq5EX1zFeJWj4rGYZv432WnYw8CbaSUeTdxPx4r573UgYU479,376,863

Het programma is upgradebaar op beide clusters. De bovenstaande cijfers zijn wat solana program show op 2 oktober 2026 meldde; voer dezelfde opdracht uit voor actuele waarden. De devnet-build is ouder dan de commit waartegen de stappenpagina's zijn geschreven (zie Installeren), met dezelfde set instructies en fouten.

Levenscyclus

Een trade is open vanaf CreateDvp totdat Settle, Cancel of Reject hem sluit. Financiering heeft geen eigen instructie: een leg is gefinancierd wanneer het escrow- account ten minste het overeengekomen bedrag bevat. Reclaim geldt per leg en laat de trade open, zodat een probleem met één leg de andere partij niet dwingt de hele trade te annuleren.

Status

Elke trade heeft één SwapDvp-account van 458 bytes, dat eigendom is van het programma. Het adres wordt afgeleid van de afwikkelautoriteit, de twee partijen, de twee mints en een nonce (de seeds ["dvp", settlement_authority, user_a, user_b, mint_a, mint_b, nonce]). De bedragen en tijden worden in het account opgeslagen en hebben geen invloed op het adres, en daarom moeten ze worden uitgelezen in plaats van afgeleid. Een klein markeringsaccount, de nonce-tombstone op ["nonce", swap_dvp], wordt samen met de trade aangemaakt en nooit gesloten, zodat elke combinatie van partijen, mints, autoriteit en nonce voor slechts één trade kan worden gebruikt.

VeldTypeBetekenis
bumpu8PDA-bump
user_a, user_bPubkeyDe twee partijen
mint_a, mint_bPubkeyDe mints van de asset-leg en de cash-leg
settlement_authorityPubkeyDe enige ondertekenaar die kan afwikkelen of annuleren
token_program_a, token_program_bPubkeyHet token program dat eigenaar is van elke mint; een trade kan SPL Token- en Token-2022-legs combineren
amount_a, amount_bu64Het overeengekomen bedrag van elke leg, in de kleinste eenheid van de mint (basiseenheden)
expiry_timestampi64Na deze netwerktijd (de onchain-klok) wordt Settle geweigerd. Reclaim, Cancel en Reject werken nog steeds
nonceu64Maakt onderscheid tussen trades die de overige seeds delen. Eenmalig te gebruiken
ref_string[u8; 64]Een ondoorzichtige clientreferentie, aangevuld met nullen; het programma leest deze nooit
user_a_settlement_destinationPubkeyOntvangt de cash-leg bij Settle; standaard user_a
user_b_settlement_destinationPubkeyOntvangt de asset-leg bij Settle; standaard user_b
mint_a_authority, mint_b_authorityPubkeyDe mint-autoriteiten die bij het aanmaken zijn vastgelegd; Settle mislukt als een van beide is gewijzigd
earliest_settlement_timestampOption<i64>Indien ingesteld, wordt Settle vóór deze netwerktijd geweigerd

De veldenlijst is overgenomen uit de IDL van het programma bij de commit die wordt genoemd onder Een trade aanmaken.

Instructies

InstructieOndertekenaarEffect
CreateDvpElke betalerMaakt het SwapDvp-record, de nonce-tombstone en beide escrowaccounts aan. Verplaatst geen tokens
ReclaimDvpuser_a of user_bStuurt de eigen leg van de ondertekenaar terug uit escrow. De trade blijft open en de leg kan opnieuw worden gefinancierd
SettleDvpAfwikkelautoriteitMaakt amount_a over naar de bestemming van user_b en amount_b naar de bestemming van user_a, stuurt eventueel overschot terug naar de partij van de leg, sluit het record en beide escrows
CancelDvpAfwikkelautoriteitStort alles wat escrow A bevat terug aan user_a en wat escrow B bevat aan user_b, sluit het record en beide escrows
RejectDvpuser_a of user_bZelfde effect als Cancel, ondertekend door een partij
RecoverDvpuser_a of user_bNadat de trade is gesloten: leegt een opnieuw aangemaakte escrow naar het eigen token account van de ondertekenaar en sluit deze. Dekt een storting die na Settle, Cancel of Reject is binnengekomen

Elke terugbetaling gaat naar het eigen associated token account van de partij voor de mint van die leg, ongeacht wie de escrow heeft gefinancierd.

De accounts en argumenten van elke instructie staan op de pagina van die stap.

Fouten

CodeFoutWanneer
0SignerNotPartyReclaim, Reject of Recover ondertekend door een adres dat niet user_a of user_b is
1DvpExpiredSettle na expiry_timestamp
2SettlementAuthorityMismatchSettle of Cancel ondertekend door een ander adres dan de afwikkelautoriteit
3SettlementTooEarlySettle vóór earliest_settlement_timestamp
4LegNotFundedSettle terwijl een escrow minder bevat dan het overeengekomen bedrag
5ExpiryNotInFutureCreate met een vervaldatum op of vóór de huidige netwerktijd
6EarliestAfterExpiryCreate met een vroegste afwikkeltijd na de vervaldatum
7SelfDvpCreate met user_a gelijk aan user_b
8SameMintCreate met mint_a gelijk aan mint_b
9ZeroAmountCreate met een bedrag van nul op een van beide legs
10BlockedMintExtensionCreate of Settle met een mint met TransferFee, InterestBearing, ScaledUiAmount of NonTransferable
11SettlementAuthorityIsPartyCreate met de afwikkelautoriteit gelijk aan een partij
12SettlementAuthorityExecutableCreate met een uitvoerbare afwikkelautoriteit
13NonceAlreadyUsedCreate dat een (seeds, nonce) hergebruikt die al een tombstone heeft
14ExpiryTooFarInFutureCreate met een vervaldatum die meer dan een jaar vooruit ligt
15RefStringTooLongCreate met een referentie die langer is dan 64 bytes
16DvpStillOpenRecover terwijl de trade nog open is; gebruik Reclaim
17DvpNeverCreatedHerstellen met seeds zonder tombstone
18EscrowPreloadedWithLamportsCreate wanneer een niet-native escrow meer lamports bevat dan het rent-exempt minimum
19SettlementDestinationIsSwapDvpCreate met een afwikkelbestemming die gelijk is aan het handelsrecord
20SwapDvpPreloadedWithLamportsCreate wanneer het recordadres meer lamports bevat dan de rent-reserve
21RecipientAtaMismatchEen token account voor de ontvanger of terugbetaling hoort niet meer bij de verwachte wallet en mint
22PartyNotSignerCapableCreate met een partij die geen niet-uitvoerbaar account is dat eigendom is van het systeem
23MintAuthorityChangedSettle wanneer de mint authority van een leg afwijkt van de waarde die bij het aanmaken is vastgelegd

Events en indexering

Het programma zendt geen onchain events uit. Een indexer of reconciliatiesysteem leest de accountstatus van SwapDvp en de tokensaldi van de twee escrows, en gebruikt ref_string om een trade te koppelen aan de bijbehorende offchain-order. Omdat het record bij de afwikkeling wordt gesloten, slaat een systeem dat achteraf de voorwaarden nodig heeft de voorwaarden op op het moment dat het ze leest, of reconstrueert het ze uit de transactie waarmee de trade is aangemaakt.

Ondersteunde tokens

Een trade kan een SPL Token-leg combineren met een Token-2022-leg; elke leg heeft zijn eigen token program. Wrapped SOL-legs worden ondersteund.

Token-2022-extensie op de mint van een legGedrag van het programma
TransferFee, InterestBearing, ScaledUiAmount, NonTransferableAfgewezen bij Create en Settle met BlockedMintExtension
PermanentDelegate, Pausable, DefaultAccountState, een freeze authority, MintCloseAuthorityGeaccepteerd; elke authority kan handelen op de tokens in escrow
ConfidentialTransferGeaccepteerd; bedragen op die leg zijn openbaar
TransferHookOndersteund, tot 32 extra accounts per leg
MemoTransfer op een bestemmings- of terugbetalingsaccountGeaccepteerd; het programma zendt de vereiste memo uit vóór de transfer

Een transfer fee zou ertoe leiden dat de ontvangende partij minder krijgt dan het afgesproken bedrag. Interest Bearing en Scaled UI Amount wijzigen de ruwe bedragen niet, maar hun rente of vermenigvuldiger kan veranderen tussen het aanmaken en het afwikkelen van een trade, waardoor de weergave van de afgesproken bedragen verandert. NonTransferable zou beide legs vastzetten.

De geaccepteerde authorities kunnen de tokens in escrow verplaatsen, bevriezen of stilleggen gedurende de looptijd van de trade (zie hieronder). De escrow kan niet worden geconfigureerd om confidential transfers te ontvangen, dus de bedragen in escrow en na afwikkeling op een confidential leg zijn openbaar.

Voor een mint met een hook lost de client de extra accounts van de hook op en voegt ze toe aan Settle, Cancel, Reject, Reclaim en Recover. De limiet van 32 per leg geldt inclusief het hookprogramma en het bijbehorende validatieaccount. Als de hook authority de accountlijst van de hook uitbreidt tot boven die limiet, mislukt elke transfer op die leg, inclusief Reclaim, Cancel, Reject en Recover, totdat de authority dit terugdraait. De accountlimiet van de transactie kan eerder worden bereikt dan de limiet per leg als beide legs hooks hebben.

Wanneer een bestemmings- of terugbetalingsaccount memo's vereist, roept het programma het Memo-programma aan vóór de transfer. Daarom heeft elke instructie die tokens uit escrow verplaatst een memo_program-account nodig.

Beperkingen voor mintconfiguratie

Scaled UI Amount. Het tokenized-security-sjabloon in Mosaic, de uitgiftetoolkit van de Solana Foundation, voegt altijd Scaled UI Amount toe, dus het programma accepteert geen mint die met dat sjabloon is aangemaakt als leg. Een mint die voor dit programma bedoeld is, kan zonder de extensie worden aangemaakt (zie Token Extensions); DvP met delegatie wordt afgewikkeld via gedelegeerde autoriteit en past deze controle niet toe.

Standaard bevroren mints. De escrow van elke trade is een associated token account dat eigendom is van een program-derived address dat nieuw is voor die trade. Bij een mint met Default Account State ingesteld op frozen wordt de escrow bevroren aangemaakt en mislukt een financieringstransfer ernaartoe totdat deze is ontdooid. Onder Token ACL betekent dat dat de uitgever of diens transferagent de escrow van de trade toelaat vóór de financiering: ofwel door het adres van het traderecord (de eigenaar van de escrow) aan de allowlist toe te voegen, zodat iedereen de escrow kan ontdooien als de Token ACL-config van de mint permissionless thaw inschakelt, ofwel door de freeze authority de escrow rechtstreeks te laten ontdooien. Een bevroren escrow blokkeert ook Settle, Reclaim, Cancel, Reject en Recover op die leg, dus de freeze authority, en bij een mint met een hook de hook authority, is gedurende de looptijd van de trade een vertrouwde partij. Het pad met een bevroren escrow wordt hier beschreven en wordt niet uitgevoerd in de devnet-snippets.

Beperkingen

  • Geen matching, prijsontdekking of orderboek. De partijen spreken de voorwaarden buiten het grootboek af en een van hen legt ze vast.
  • Geen netting, en alleen bilateraal: één record is één trade tussen twee partijen.
  • Geen gedeeltelijke uitvoering. Settle verplaatst precies het afgesproken bedrag van elke leg en stort een eventueel overschot terug aan de partij van de leg.
  • Geen leg buiten het grootboek. Beide legs zijn token accounts op Solana; een cashleg via bestaande kanalen wordt apart afgewikkeld en gereconcilieerd.
  • Geen geschiktheidscontrole, allowlist of KYC. De eigen controles van de mint dwingen de geschiktheid van houders af.
  • Geen automatische afwikkeling. De settlement authority moet ondertekenen.
  • Geen events en geen protocolkosten naast transactiekosten en rent.

Het programma neemt het principale risico tussen de twee partijen weg: geen van beide legs verplaatst tenzij beide dat doen. Het neemt het krediet- of aflossingsrisico van de uitgever op beide tokens niet weg, evenmin als de mogelijkheid van de freeze-, pause- of permanent delegate-authority van een mint om te handelen op tokens in escrow (zie ondersteunde tokens), of de afhankelijkheid van de beschikbaarheid van de settlement authority om te ondertekenen.

Verificatie vóór financiering en afwikkeling

CreateDvp is permissionless: alleen de payer ondertekent, de partijen en de settlement authority niet. Iedereen kan dus een record aanmaken met willekeurige partijen en voorwaarden. Lees vóór de financiering, en opnieuw vóór de afwikkeling, het SwapDvp-account en controleer:

  1. Het account is eigendom van het DvP-programma en is precies 458 bytes groot. Een account dat niet eigendom is van het programma kan worden gevuld met bytes die eruitzien als een echt record.
  2. user_a, user_b, mint_a, mint_b en settlement_authority komen overeen met de afgesproken trade.
  3. amount_a, amount_b, expiry_timestamp en earliest_settlement_timestamp komen overeen met de afgesproken voorwaarden.
  4. Beide afwikkelbestemmingen zijn de afgesproken adressen. Een vervalst record kan de opbrengsten omleiden.

De legs financieren somt de gecontroleerde readers van de gegenereerde clients op en toont de controle in code.

Beschouw een trade als afgewikkeld wanneer de Settle-transactie finalized bereikt. Dat is een commitmentniveau van het netwerk; of het ook de definitiviteit van de afwikkeling in juridische zin markeert, hangt af van de afspraken tussen de partijen en de toepasselijke regelgeving.

Versiebeheer

Het SwapDvp-account heeft geen versieveld. De indeling is vastgelegd op 458 bytes (SwapDvp::LEN) en de gecontroleerde readers weigeren een account met een andere lengte. De IDL heeft zijn eigen versie, 0.1.0 per 2 oktober 2026.

Het programma is upgradeable op beide clusters (zie Program-ID). Een traderecord bestaat alleen totdat het is afgewikkeld, geannuleerd of afgewezen. Raadpleeg dus de repository om te zien hoe een upgrade omgaat met openstaande trades, en genereer clients opnieuw op basis van de IDL van de gedeployde build.

Repository en audit

Broncode, IDL, gegenereerde clients en tests staan in solana-foundation/dvp onder de MIT-licentie. Het programma is een no_std Pinocchio-programma; de clients worden gegenereerd uit de IDL met Codama. Meldingen van kwetsbaarheden verlopen via de link naar het security advisory van de repository, conform SECURITY.md.

Het programma is geaudit door Cantina.

Gerelateerd

Is this page helpful?

© 2026 Solana Foundation. Alle rechten voorbehouden.