L'alimentation se fait par un simple TransferChecked vers l'escrow de la jambe : tout portefeuille ou système
de conservation capable d'envoyer un transfert de token peut donc alimenter une jambe. Seule la lecture de
l'enregistrement du trade avant l'alimentation nécessite le client DvP. Le programme ne vérifie les soldes
d'escrow qu'au règlement ; rien ne contrôle le transfert à son arrivée, c'est pourquoi
chaque partie lit l'enregistrement du trade avant de transférer.
Cette page fait suite à la création d'un trade ; le client et les signataires sont repris tels quels.
Vérifier les conditions
La création d'un enregistrement ne requiert aucune autorisation, et les adresses d'escrow sont dérivées
uniquement de l'enregistrement et du mint, jamais des conditions. Un transfert vers un escrow peut
donc aboutir sur des conditions que vous n'avez jamais acceptées, notamment des destinations de règlement
qui redirigent le produit de votre contrepartie vers une tierce adresse.
Avant d'alimenter, lisez le compte SwapDvp et comparez-le au trade convenu.
verifySwapDvp en TypeScript et verify::decode_swap_dvp_account en Rust
confirment que le compte appartient au programme DvP, fait exactement 458 octets et
se trouve à l'adresse que dérivent ses propres champs (fetchSwapDvpChecked n'effectue
que les deux premières vérifications). Les lecteurs simples fetchSwapDvp et decodeSwapDvp
n'en effectuent aucune. Les vérifications portant sur les parties, les montants, les dates et les destinations
restent à la charge de l'appelant, par comparaison avec le trade convenu.
import { unwrapOption } from "@solana/kit";import { verifySwapDvp } from "./dvp";const trade = await verifySwapDvp(client.rpc, swapDvp);const t = trade.data;const expectedAmountA = 1_000_000_000n;const expectedAmountB = 998_500_000n;const expectedEarliestSettlement: bigint | null = null; // as agreedconst expectedExpiry = 1_798_761_600n; // as agreed, unix secondsif (t.userA !== userA ||t.userB !== userB ||t.mintA !== mintA ||t.mintB !== mintB ||t.settlementAuthority !== settlementAuthority ||t.tokenProgramA !== tokenProgramA ||t.tokenProgramB !== tokenProgramB ||t.amountA !== expectedAmountA ||t.amountB !== expectedAmountB ||unwrapOption(t.earliestSettlementTimestamp) !== expectedEarliestSettlement ||t.expiryTimestamp !== expectedExpiry ||t.userASettlementDestination !== userA ||t.userBSettlementDestination !== userB) {throw new Error("Stored terms do not match the agreed trade; do not fund");}if (t.expiryTimestamp <= BigInt(Math.floor(Date.now() / 1000)) + 60n) {throw new Error("Trade expires too soon to fund safely");}
Si l'enregistrement a été créé par votre contrepartie ou par l'autorité de règlement, comparez chaque champ aux conditions convenues hors registre. Si vous l'avez créé vous-même, cette lecture confirme qu'il est arrivé tel qu'il a été envoyé.
Transférer vers l'escrow
Alimentez la jambe avec exactement le montant convenu. Le programme plafonne le règlement à
amount_x et renvoie tout excédent à la partie de la jambe ; un excédent n'est donc pas perdu,
mais il ajoute un second transfert au règlement et peut échouer avec certains
transfer hooks (voir les notes ci-dessous).
Utilisez TransferChecked, et non un Transfer non vérifié. Les mints Token-2022 dotés
d'extensions qui dépendent du mint account, comme Pausable, rejettent un transfert
qui ne le fournit pas, et un mint avec transfer hook exige que les comptes du hook
soient résolus et ajoutés de la même manière que pour tout autre transfert de ce
token.
La partie de la jambe d'actif, signant en tant que userASigner, alimente l'escrow A :
import {findAssociatedTokenPda,getTransferCheckedInstruction,} from "@solana-program/token-2022";const [userAAtaA] = await findAssociatedTokenPda({mint: mintA,owner: userA,tokenProgram: tokenProgramA,});const [userBAtaB] = await findAssociatedTokenPda({mint: mintB,owner: userB,tokenProgram: tokenProgramB,});const fundAssetLeg = getTransferCheckedInstruction({source: userAAtaA,mint: mintA,destination: escrowA,authority: userASigner,amount: t.amountA,decimals: 6,}, { programAddress: tokenProgramA });await client.sendTransaction([fundAssetLeg]);
La partie de la jambe de liquidités fait de même pour l'escrow B avec userBAtaB, mintB,
userBSigner, t.amountB et { programAddress: tokenProgramB }.
Un transfert d'alimentation observé au statut confirmed
peut encore être remplacé. Le programme lit le solde de l'escrow onchain au
règlement ; un Settle envoyé alors qu'un transfert d'alimentation n'a pas abouti échoue
avec LegNotFunded et rien ne bouge ; le coût se limite à un Settle échoué et à une nouvelle tentative.
Considérez une jambe comme alimentée lorsque son transfert est finalized.
Notes
- Jambes en SOL wrappé. Le programme lit le solde d'un escrow natif après l'avoir synchronisé ; les lamports envoyés vers un escrow en SOL wrappé par un transfert système sont donc comptabilisés. N'envoyez jamais de SOL vers l'escrow d'un autre mint : le programme ne peut pas le restituer, et il revient à celui qui ferme le compte.
- Mints à accès restreint. Sur un mint dont l'état de compte par défaut (Default Account State) est gelé, l'escrow est créé gelé et le transfert échoue tant que l'émetteur ne l'a pas dégelé ou admis. La vue d'ensemble décrit l'interaction avec Token ACL.
- Transfer hooks. Alimentez les escrows dotés de hooks avec exactement le montant convenu. Si un excédent impose un remboursement au règlement, celui-ci réutilise les comptes du hook de la jambe avec une destination et un montant différents, ce que certains hooks rejettent. La solution consiste à faire un Reclaim, à réalimenter avec le montant exact, puis à relancer le règlement.
- Alimentation après l'expiration. Rien n'empêche un transfert après
expiry_timestamp. Il aboutit, le règlement n'est plus possible, et la partie de la jambe le récupère avec Reclaim tant que le trade est ouvert, ou avec Recover une fois celui-ci clos. Voir annuler un trade. - Qui alimente en premier. Le programme n'impose aucun ordre entre les deux jambes. L'ordre est laissé aux parties ; chaque côté peut récupérer sa propre jambe à tout moment avant le règlement, sauf si une autorité du mint (gel, pause ou transfer hook) bloque l'escrow.
Étapes suivantes
- Régler le trade : l'autorité de règlement échange les deux jambes en une seule transaction
- Annuler un trade : récupérer une jambe alimentée lorsque le trade n'est pas réglé
Is this page helpful?