Delivery vs Payment (DvP)-programma

Het DvP-programma is het standaardprogramma voor delivery versus payment 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 escrow-account, en een afwikkelautoriteit wikkelt beide legs af in één transactie, zodat of beide legs worden verplaatst, of geen van beide. De afwikkelautoriteit is een derde adres dat in de trade wordt genoemd, zoals de handelsplaats of de 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 verzenden, kan een leg funden 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 handelt

Het aanmaken van een traderecord is permissionless, dus een record is geen bewijs van overeenstemming. Elke partij leest de opgeslagen voorwaarden voordat zij funden, en de afwikkelautoriteit voordat die afwikkelt (zie verificatie).

Hoe het werkt

Elke trade krijgt een record dat eigendom is van het programma en twee escrow-accounts, één per leg. De partij van de asset-leg (user_a) en de partij van de cash-leg (user_b) funden elk een leg door tokens over te maken naar het escrow-account van die leg. De afwikkelautoriteit is de enige ondertekenaar die kan afwikkelen. Bij de afwikkeling wordt het afgesproken bedrag van elke leg naar de andere kant overgemaakt, wordt eventueel overschot teruggegeven aan de partij die eigenaar is van de leg, en worden het record en beide escrows gesloten. De atomiciteit komt voort uit Solana- transacties: beide overdrachten zitten in één transactie, dus of beide worden doorgevoerd, of geen van beide.

Elke terugbetaling, elk terugvorderen en elke teruggave van overschot 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 funden vanuit een eigen account, maar alles wat wordt teruggegeven komt terecht in het account van de partij, niet terug bij de bewaarder. Elke trade laat ook een permanent markeringsaccount achter (zie State).

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, fundt beide escrows met standaard tokenoverdrachten en wikkelt beide legs af in één transactie.

Kiezen tussen het programma en delegatie

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

  • Het programma vereist geen delegatie, dus de limiet van één delegate per token account is niet van toepassing, en de afwikkelautoriteit kan de opbrengsten niet omleiden. Elke trade is afhankelijk van een upgradeable programma en de bijbehorende upgrade authority.
  • 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 aangemaakt 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 cash-instrument is. Twee assets, of twee stablecoins, worden op dezelfde manier afgewikkeld.

RolWieOndertekentOpmerkingen
Partij van de asset-leguser_a, levert mint_aEigen fundingoverdracht; Reclaim, Reject, RecoverEen keypair-wallet, of een op 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 fundingoverdracht; Reclaim, Reject, RecoverDezelfde vereiste
AfwikkelautoriteitEen derde adres dat bij het aanmaken wordt genoemdSettle, CancelDe enige ondertekenaar die kan afwikkelen. Deze kan de opbrengsten, die bij het aanmaken zijn vastgelegd, niet omleiden. Bij afwikkeling of annulering ontvangt deze de rent van de gesloten accounts
Betaler van de rentWie CreateDvp ondertekentCreateBetaalt de rent (de SOL-storting die een account open houdt) voor het record, de nonce tombstone en beide escrows. Wordt niet vastgelegd als ontvanger van rent: de rent van gesloten accounts gaat naar degene die de trade sluit

Program-ID

dvp34bdbcEm4f4FCUjGV4mDAkDshaQR4LkK8fdcsyZq
ClusterProgrammaUpgrade authorityLaatst gedeployde slot
mainnet-betadvp34bdbcEm4f4FCUjGV4mDAkDshaQR4LkK8fdcsyZqDXtFpbPjcn2hxPnw79x1Pfoj35vXh5AsWBkS37YnXMVv452,058,374
devnetdvp34bdbcEm4f4FCUjGV4mDAkDshaQR4LkK8fdcsyZq5EX1zFeJWj4rGYZv432WnYw8CbaSUeTdxPx4r573UgYU479,376,863

Het programma is upgradeable op beide clusters. De bovenstaande cijfers zijn wat solana program show rapporteerde op 2 oktober 2026; voer hetzelfde commando uit voor actuele waarden. De devnet-build is ouder dan de commit waarop de stappenpagina's zijn gebaseerd (zie Installatie), met dezelfde set instructies en fouten.

Levenscyclus

Een trade is open vanaf CreateDvp totdat Settle, Cancel of Reject deze sluit. Funding heeft geen eigen instructie: een leg is gefund wanneer het escrow- account minstens het afgesproken bedrag bevat. Reclaim geldt per leg en laat de trade open, zodat een probleem met één leg de andere partij niet dwingt om de hele trade te annuleren.

State

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, waardoor ze moeten 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 afgesproken 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 authorities zoals vastgelegd bij het aanmaken; Settle mislukt als een van beide is gewijzigd
earliest_settlement_timestampOption<i64>Indien ingesteld wordt Settle vóór deze netwerktijd geweigerd

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

Instructies

InstructieOndertekenaarEffect
CreateDvpElke betalerMaakt het SwapDvp-record, de bijbehorende nonce tombstone en beide escrow-accounts aan. Verplaatst geen tokens
ReclaimDvpuser_a of user_bGeeft de eigen leg van de ondertekenaar terug uit de escrow. De trade blijft open en de leg kan opnieuw worden gefund
SettleDvpAfwikkelautoriteitMaakt amount_a over naar de bestemming van user_b en amount_b naar de bestemming van user_a, geeft eventueel overschot terug aan de partij van de leg en sluit het record en beide escrows
CancelDvpAfwikkelautoriteitBetaalt wat escrow A bevat terug aan user_a en wat escrow B bevat aan user_b, en sluit het record en beide escrows
RejectDvpuser_a of user_bHetzelfde effect als Cancel, maar 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 gefund.

De accounts en argumenten van elke instructie staan op de pagina van de betreffende 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 afgesproken bedrag
5ExpiryNotInFutureCreate met een vervaltijd op of vóór de huidige netwerktijd
6EarliestAfterExpiryCreate met een vroegste afwikkeltijd na de vervaltijd
7SelfDvpCreate waarbij user_a gelijk is aan user_b
8SameMintCreate waarbij mint_a gelijk is aan mint_b
9ZeroAmountCreate met een bedrag van nul op een van beide legs
10BlockedMintExtensionCreate of Settle met een mint die TransferFee, InterestBearing, ScaledUiAmount of NonTransferable bevat
11SettlementAuthorityIsPartyCreate waarbij de afwikkelautoriteit gelijk is aan een van de partijen
12SettlementAuthorityExecutableCreate met een uitvoerbare afwikkelautoriteit
13NonceAlreadyUsedCreate dat een (seeds, nonce) hergebruikt waarvoor al een tombstone bestaat
14ExpiryTooFarInFutureCreate met een vervaltijd 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 die geen tombstone hebben
18EscrowPreloadedWithLamportsAanmaken wanneer een niet-native escrow meer lamports bevat dan het rent-exempt minimum
19SettlementDestinationIsSwapDvpAanmaken met een afwikkelingsbestemming die gelijk is aan het transactiedossier
20SwapDvpPreloadedWithLamportsAanmaken wanneer het dossieradres meer lamports bevat dan de rent-reserve
21RecipientAtaMismatchEen token account van een ontvanger of voor terugbetaling hoort niet langer bij de verwachte wallet en mint
22PartyNotSignerCapableAanmaken met een partij die geen systeemeigen, niet-uitvoerbaar account is
23MintAuthorityChangedAfwikkelen wanneer de mint authority van een leg afwijkt van de waarde die bij het aanmaken is vastgelegd

Events en indexering

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

Ondersteunde tokens

Een transactie 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, NonTransferableGeweigerd bij Create en Settle met BlockedMintExtension
PermanentDelegate, Pausable, DefaultAccountState, een freeze authority, MintCloseAuthorityGeaccepteerd; elke authority kan handelen op de in escrow geplaatste tokens
ConfidentialTransferGeaccepteerd; bedragen op die leg zijn openbaar
TransferHookOndersteund, tot 32 extra accounts per leg
MemoTransfer op een bestemmings- of terugbetalingsaccountGeaccepteerd; het programma verzendt de vereiste memo vóór de overdracht

Een transferkost 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 multiplier kan veranderen tussen het aanmaken en het afwikkelen van een transactie, waardoor de weergave van de afgesproken bedragen verandert. NonTransferable zou beide legs vastzetten.

De geaccepteerde authorities kunnen de in escrow geplaatste tokens verplaatsen, bevriezen of stopzetten gedurende de looptijd van de transactie (zie hieronder). De escrow kan niet worden geconfigureerd om vertrouwelijke overdrachten te ontvangen, dus de in escrow geplaatste en afgewikkelde bedragen op een vertrouwelijke 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 omvat het hookprogramma en het bijbehorende validatieaccount. Als de hook authority de accountlijst van de hook uitbreidt tot voorbij die limiet, mislukt elke overdracht op die leg, inclusief Reclaim, Cancel, Reject en Recover, totdat de authority dit terugdraait. De limiet voor het aantal accounts per transactie kan eerder bereikt worden dan de limiet per leg wanneer beide legs hooks hebben.

Wanneer een bestemmings- of terugbetalingsaccount memo's vereist, roept het programma het Memo- programma aan vóór de overdracht, en 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 issuance-toolkit 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 transactie is een associated token account dat eigendom is van een program-derived address dat nieuw is voor die transactie. Bij een mint met Default Account State ingesteld op frozen wordt de escrow bevroren aangemaakt en mislukt een financieringsoverdracht ernaartoe totdat deze is ontdooid. Onder Token ACL betekent dat dat de uitgever of zijn transfer agent de escrow van de transactie toelaat vóór de financiering: ofwel door het adres van het transactiedossier (de eigenaar van de escrow) aan de allowlist toe te voegen, zodat iedereen de escrow kan ontdooien als de Token ACL-configuratie van de mint permissionless thaw toestaat, of door de freeze authority deze 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 een vertrouwde partij voor de looptijd van de transactie. Het pad met een bevroren escrow wordt hier beschreven en wordt niet uitgeoefend in de devnet-snippets.

Beperkingen

  • Geen matching, prijsontdekking of orderboek. De partijen komen de voorwaarden buiten het grootboek overeen en een van hen legt ze vast.
  • Geen netting, en alleen bilateraal: één dossier is één transactie tussen twee partijen.
  • Geen gedeeltelijke uitvoering. Settle verplaatst precies het afgesproken bedrag van elke leg en geeft een eventueel overschot terug aan de partij van de leg.
  • Geen leg buiten het grootboek. Beide legs zijn token accounts op Solana; een cash-leg via bestaande rails 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 tekenen.
  • Geen events en geen protocolkosten behalve transactiekosten en rent.

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

Verificatie vóór financiering en afwikkeling

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

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

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

Beschouw een transactie 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 overeenkomsten van de partijen en de toepasselijke regelgeving.

Versiebeheer

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

Het programma is upgradebaar op beide clusters (zie Program ID). Een transactiedossier bestaat alleen tot het is afgewikkeld, geannuleerd of afgewezen, dus controleer in de repository hoe een upgrade met openstaande transacties omgaat, 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. Kwetsbaarheidsmeldingen 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.