Nạp vốn cho các leg

Nạp vốn chỉ là một lệnh TransferChecked thông thường vào escrow của leg, vì vậy bất kỳ ví hoặc hệ thống lưu ký nào có thể gửi chuyển token đều có thể nạp vốn cho một leg. Chỉ bước đọc bản ghi giao dịch trước khi nạp vốn mới cần đến DvP client. Chương trình chỉ kiểm tra số dư escrow tại thời điểm quyết toán; không có gì kiểm tra giao dịch chuyển khi nó được ghi nhận, nên mỗi bên cần đọc bản ghi giao dịch trước khi chuyển.

Trang này tiếp nối phần tạo giao dịch; client và các signer được giữ nguyên.

Xác minh các điều khoản

Việc tạo bản ghi không cần cấp quyền, và các địa chỉ escrow được suy ra chỉ từ bản ghi và mint, không bao giờ từ các điều khoản. Do đó, một giao dịch chuyển vào escrow có thể được ghi nhận theo những điều khoản mà bạn chưa từng đồng ý, bao gồm các đích quyết toán chuyển hướng số tiền thu được của đối tác của bạn sang một địa chỉ thứ ba. Trước khi nạp vốn, hãy đọc tài khoản SwapDvp và đối chiếu với giao dịch đã thỏa thuận.

verifySwapDvp trong TypeScript và verify::decode_swap_dvp_account trong Rust xác nhận rằng tài khoản thuộc sở hữu của chương trình DvP, có kích thước đúng 458 byte, và nằm tại địa chỉ được suy ra từ chính các trường của nó (fetchSwapDvpChecked chỉ thực hiện hai kiểm tra đầu tiên). Các hàm đọc thông thường fetchSwapDvp và decodeSwapDvp không thực hiện kiểm tra nào trong số này. Việc kiểm tra các bên, số lượng, thời gian và đích đến do bên gọi thực hiện, đối chiếu với giao dịch đã thỏa thuận.

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");
}

Nếu bản ghi do đối tác của bạn hoặc cơ quan quyết toán tạo ra, hãy so sánh từng trường với các điều khoản mà bạn đã thỏa thuận ngoài sổ cái. Nếu bạn tự tạo bản ghi, lần đọc này xác nhận rằng nó đã được ghi nhận đúng như khi gửi.

Chuyển vào escrow

Hãy nạp vốn cho leg đúng bằng số lượng đã thỏa thuận. Chương trình giới hạn quyết toán ở amount_x và trả lại phần dư cho bên của leg, vì vậy phần dư không bị mất, nhưng nó làm phát sinh thêm một giao dịch chuyển tại thời điểm quyết toán và có thể thất bại với một số transfer hook (xem phần ghi chú bên dưới).

Hãy dùng TransferChecked, không dùng Transfer không kiểm tra. Các mint Token-2022 có các extension phụ thuộc vào mint account, chẳng hạn như Pausable, sẽ từ chối giao dịch chuyển nếu không cung cấp nó, và mint có transfer hook cần các tài khoản của hook được phân giải và thêm vào theo cách tương tự như với bất kỳ giao dịch chuyển nào khác của token đó.

Bên nắm leg tài sản, ký bằng userASigner, nạp vốn cho 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]);

Bên nắm leg tiền mặt thực hiện tương tự cho escrow B với userBAtaB, mintB, userBSigner, t.amountB và { programAddress: tokenProgramB }.

Một giao dịch chuyển nạp vốn được thấy ở trạng thái confirmed vẫn có thể bị thay thế. Chương trình đọc số dư escrow onchain tại thời điểm quyết toán, nên lệnh Settle gửi dựa trên một giao dịch chuyển nạp vốn chưa được ghi nhận sẽ thất bại với lỗi LegNotFunded và không có gì được di chuyển; cái giá phải trả là một lệnh Settle thất bại và phải thử lại. Chỉ coi một leg là đã được nạp vốn khi giao dịch chuyển của nó ở trạng thái finalized.

Ghi chú

  • Các leg SOL được wrap. Chương trình đọc số dư của escrow native sau khi đồng bộ hóa nó, nên lamport được gửi đến escrow wrapped-SOL bằng lệnh chuyển của system đều được tính. Không bao giờ gửi SOL đến escrow của bất kỳ mint nào khác: chương trình không thể trả lại, và nó sẽ thuộc về bất kỳ ai đóng tài khoản.
  • Các mint có kiểm soát truy cập. Với mint có Default Account State là frozen, escrow được tạo ở trạng thái frozen và giao dịch chuyển sẽ thất bại cho đến khi issuer mở khóa hoặc chấp nhận nó. Phần tổng quan mô tả tương tác với Token ACL.
  • Transfer hook. Hãy nạp vốn cho các escrow có hook đúng bằng số lượng đã thỏa thuận. Nếu phần dư buộc phải hoàn trả tại thời điểm quyết toán, việc hoàn trả sẽ dùng lại các tài khoản hook của leg với đích đến và số lượng khác, điều mà một số hook sẽ từ chối. Cách khắc phục là Reclaim, nạp vốn lại đúng số lượng, rồi quyết toán lại.
  • Nạp vốn sau thời hạn hết hiệu lực. Không có gì ngăn một giao dịch chuyển sau expiry_timestamp. Nó vẫn được ghi nhận, nhưng không thể quyết toán nữa, và bên của leg thu hồi nó bằng Reclaim khi giao dịch còn mở hoặc Recover sau khi giao dịch đóng. Xem hoàn tác giao dịch.
  • Ai nạp vốn trước. Chương trình không sắp xếp thứ tự giữa hai leg. Thứ tự do các bên tự quyết định; mỗi bên có thể reclaim leg của mình bất kỳ lúc nào trước khi quyết toán, trừ khi mint authority (freeze, pause hoặc transfer hook) chặn escrow.

Các bước tiếp theo

Is this page helpful?

Mục lục

Chỉnh sửa trang