Financer les jambes

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 agreed
const expectedExpiry = 1_798_761_600n; // as agreed, unix seconds
if (
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

Is this page helpful?

Table des matières

Modifier la page
© 2026 Fondation Solana. Tous droits réservés.