Le financement est un simple TransferChecked vers l'escrow de la jambe : tout portefeuille ou système
de conservation capable d'envoyer un transfert de jetons peut donc financer une jambe. Seule la lecture
du registre de la transaction avant le financement nécessite le client DvP. Le programme ne vérifie
les soldes des escrows qu'au règlement ; rien ne contrôle le transfert à son arrivée,
donc chaque partie lit le registre de la transaction avant de transférer.
Cette page fait suite à la création d'une transaction ; le client et les signataires sont repris tels quels.
Vérifier les conditions
La création d'un registre est sans permission, et les adresses d'escrow sont dérivées uniquement
du registre et du mint, jamais des conditions. Un transfert vers un escrow peut
donc arriver avec des conditions que vous n'avez jamais acceptées, notamment des destinations
de règlement qui redirigent les produits de votre contrepartie vers une tierce adresse.
Avant de financer, lisez le compte SwapDvp et comparez-le à la transaction
convenue.
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 dérivée de 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 délais et les destinations
relèvent de l'appelant, qui les effectue par rapport à la transaction convenue.
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 le registre 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
Financez la jambe exactement au montant convenu. Le programme plafonne le règlement à
amount_x et restitue 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 hooks
de transfert (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 un hook de transfert 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
jeton.
La partie de la jambe actif, signant en tant que userASigner, finance 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 espèces fait de même pour l'escrow B avec userBAtaB, mintB,
userBSigner, t.amountB et { programAddress: tokenProgramB }.
Un transfert de financement 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 de financement 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 financé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 à un escrow de SOL wrappé par un transfert système sont donc comptabilisés. N'envoyez jamais de SOL à un escrow associé à un autre mint : le programme ne peut pas le restituer, et il revient à la personne 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.
- Hooks de transfert. Financez les escrows dotés de hooks exactement au montant convenu. Si un excédent impose un remboursement au règlement, ce remboursement réutilise les comptes de hook de la jambe avec une destination et un montant différents, ce que certains hooks rejettent. La solution consiste à effectuer un Reclaim, à refinancer au montant exact, puis à relancer le règlement.
- Financement après expiration. Rien n'empêche un transfert après
expiry_timestamp. Il arrive, le règlement n'est plus possible, et la partie de la jambe le récupère avec Reclaim tant que la transaction est ouverte, ou avec Recover après sa clôture. Voir annuler une transaction. - Qui finance en premier. Le programme n'impose aucun ordre entre les deux jambes. L'ordre relève des parties ; chacune peut récupérer sa propre jambe à tout moment avant le règlement, sauf si une autorité du mint (gel, pause ou hook de transfert) bloque l'escrow.
Étapes suivantes
- Régler la transaction : l'autorité de règlement échange les deux jambes en une seule transaction
- Annuler une transaction : récupérer une jambe financée lorsque la transaction n'est pas réglée
Is this page helpful?