O financiamento é uma simples TransferChecked para o escrow da perna, de modo que qualquer carteira ou sistema de
custódia capaz de enviar uma transferência de token pode financiar uma perna. Somente a leitura do
registro da negociação antes do financiamento exige o cliente DvP. O programa verifica os
saldos do escrow apenas na liquidação; nada verifica a transferência quando ela chega,
portanto cada parte lê o registro da negociação antes de transferir.
Esta página dá continuidade a criar uma negociação; o cliente e os signatários são reaproveitados.
Verificar os termos
A criação de um registro não exige permissão, e os endereços de escrow derivam apenas do
registro e do mint, nunca dos termos. Uma transferência para um escrow pode,
portanto, chegar vinculada a termos com os quais você nunca concordou, incluindo destinos de
liquidação que redirecionam os recursos da sua contraparte para um terceiro endereço.
Antes de financiar, leia a conta SwapDvp e confira-a com a negociação
acordada.
verifySwapDvp em TypeScript e verify::decode_swap_dvp_account em Rust
confirmam que a conta pertence ao programa DvP, tem exatamente 458 bytes e
está no endereço derivado dos seus próprios campos (fetchSwapDvpChecked executa
apenas as duas primeiras verificações). Os leitores simples fetchSwapDvp e decodeSwapDvp
não fazem nenhuma dessas verificações. As verificações de partes, valores, prazos e destinos ficam
a cargo de quem chama, comparando com a negociação acordada.
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");}
Se o registro foi criado pela sua contraparte ou pela autoridade de liquidação, compare cada campo com os termos que você acordou fora do ledger. Se você mesmo o criou, esta leitura confirma que ele chegou como foi enviado.
Transferir para o escrow
Financie a perna exatamente no valor acordado. O programa limita a liquidação a
amount_x e devolve qualquer excedente à parte da perna, portanto o excedente não se perde,
mas gera uma segunda transferência na liquidação e pode falhar com alguns transfer
hooks (veja as observações abaixo).
Use TransferChecked, não uma Transfer sem verificação. Mints do Token-2022 com
extensões que dependem da mint account, como Pausable, rejeitam uma transferência
que não a informe, e um mint com transfer hook exige que as contas do hook
sejam resolvidas e anexadas da mesma forma que em qualquer outra transferência desse
token.
A parte da perna de ativo, assinando como userASigner, financia o 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]);
A parte da perna de dinheiro faz o mesmo para o escrow B com userBAtaB, mintB,
userBSigner, t.amountB e { programAddress: tokenProgramB }.
Uma transferência de financiamento vista em confirmed
ainda pode ser substituída. O programa lê o saldo do escrow on-chain na
liquidação, portanto um Settle enviado com base em uma transferência de financiamento que não foi concluída falha
com LegNotFunded e nada é movimentado; o custo é um Settle com falha e uma nova tentativa.
Considere uma perna financiada quando a sua transferência estiver finalized.
Observações
- Pernas em SOL encapsulado. O programa lê o saldo de um escrow nativo após sincronizá-lo, de modo que os lamports enviados a um escrow de SOL encapsulado por uma transferência do sistema são contabilizados. Nunca envie SOL para um escrow de qualquer outro mint: o programa não consegue devolvê-lo, e ele vai para quem fechar a conta.
- Mints com restrição de acesso. Em um mint com Default Account State congelado, o escrow é criado congelado e a transferência falha até que o emissor o descongele ou o autorize. A visão geral descreve a interação com o Token ACL.
- Transfer hooks. Financie escrows com hook exatamente no valor acordado. Se um excedente forçar um reembolso na liquidação, o reembolso reutiliza as contas de hook da perna com um destino e um valor diferentes, o que alguns hooks rejeitam. A recuperação é Reclaim, refinanciar no valor exato e liquidar novamente.
- Financiamento após o vencimento. Nada impede uma transferência após
expiry_timestamp. Ela chega, a liquidação deixa de ser possível, e a parte da perna a recupera com Reclaim enquanto a negociação está aberta ou com Recover depois que ela é encerrada. Veja desfazer uma negociação. - Quem financia primeiro. O programa não define a sequência das duas pernas. A ordem é uma questão entre as partes; qualquer lado pode reaver a sua própria perna a qualquer momento antes da liquidação, a menos que uma autoridade do mint (congelamento, pausa ou transfer hook) bloqueie o escrow.
Próximos passos
- Liquidar a negociação: a autoridade de liquidação troca as duas pernas em uma única transação
- Desfazer uma negociação: recuperar uma perna financiada quando a negociação não é liquidada
Is this page helpful?