Trang này được dịch tự động bằng AI. Phiên bản tiếng Anh là bản chính thức.Xem bản tiếng Anh →
PDA (program-derived addresses) và CPI (cross-program invocation) là hai nguyên thủy tạo nên Raydium. PDA cho phép một chương trình “sở hữu” các địa chỉ xác định mà không cần khóa riêng — đó là cách các pool authority và vault hoạt động. CPI cho phép một chương trình gọi chương trình khác — đó là cách Raydium hoán đổi token thông qua chương trình SPL Token và cách các nhà tích hợp kết hợp Raydium vào luồng của họ. Cả hai đều đáng hiểu trước khi đọc mã nguồn của Raydium.
PDA: địa chỉ không có khóa
Program-Derived Address là một khóa công khai có các đặc điểm:- Không nằm trên đường cong ed25519 (không có khóa riêng tồn tại cho nó).
- Được dẫn xuất một cách xác định từ một ID chương trình và một tập hợp các seed.
- Chỉ có thể được ký bởi chương trình dẫn xuất, thông qua
invoke_signed.
Dẫn xuất
Một PDA được tính bằng cách băm ID chương trình với các seed, sau đó tìm một byte “bump” để buộc kết quả ra khỏi đường cong. Bump đầu tiên (thường bắt đầu từ 255 và giảm dần) tạo ra một địa chỉ ngoài đường cong sẽ thắng; đây là canonical bump.u64 dưới dạng byte little-endian. Quy ước của Raydium là một tiền tố dễ đọc theo sau bởi các định danh duy nhất.
Mẫu PDA của Raydium
Các PDA phổ biến trong các chương trình của Raydium:
Người dùng và nhà tích hợp có thể tính toán những điều này mà không cần tìm nạp bất cứ thứ gì — với các đầu vào công khai (pool ID, farm ID, khóa người dùng), PDA là xác định.
Canonical bump
Mặc dù về nguyên tắc có thể có nhiều bump tạo ra các địa chỉ ngoài đường cong, các chương trình của Raydium luôn sử dụng canonical bump (được tìm thấy bằng cách giảm dần từ 255). Điều này được lưu trữ trong dữ liệu tài khoản của PDA để các giao dịch tiếp theo có thể chuyển nó vào và bỏ qua vòng lặp dẫn xuất (tốn kém):PoolState lưu trữ bump: [u8; 1] thay thế, vì vậy hãy kiểm tra struct của chương trình cụ thể thay vì giả định một hình dạng.)
Trong các giao dịch tiếp theo, bump được đọc từ trạng thái pool thay vì được tính toán lại.
CPI: gọi các chương trình khác
Cross-Program Invocation cho phép một chương trình gọi các hướng dẫn của chương trình khác trong một giao dịch. Raydium sử dụng CPI rộng rãi:- Các hướng dẫn swap gọi chương trình SPL Token để di chuyển token.
- CLMM gọi Metaplex để mint position NFT.
- Tạo pool gọi System Program để cấp phát tài khoản.
- Farm v6 gọi SPL Token để chuyển phần thưởng.
integration-guides/cpi-integration.
invoke vs invoke_signed
Runtime Solana cung cấp hai nguyên thủy CPI:invoke: gọi chương trình khác; chương trình được gọi kế thừa các người ký của giao dịch bên ngoài.invoke_signed: gọi chương trình khác thay mặt cho một PDA; runtime xác minh các seed của PDA và ủy quyền chữ ký.
invoke_signed là điều kỳ diệu cho phép các chương trình giữ quyền kiểm soát các tài khoản mà không cần quản lý khóa riêng.
Ví dụ: Raydium chuyển từ pool vault
Một pool vault là một Token Account có quyền kiểm soát là PDA của chương trình pool. Để chuyển token ra ngoài trong quá trình swap, chương trình pool phải ký với tư cách là PDA đó:invoke_signed được gọi bởi chương trình CPMM, xác minh rằng vault_and_lp_mint_auth_seed + bump dẫn xuất đến địa chỉ của pool_authority khi được băm với ID chương trình CPMM, và cho phép chữ ký quyền kiểm soát trên chuyển token. Không có khóa riêng liên quan.
Ví dụ: nhà tích hợp gọi Raydium CPMM
Một chương trình nhà tích hợp (ví dụ: một escrow) có thể gọiswap_base_input của Raydium thông qua CPI:
integration-guides/cpi-integration để có ví dụ escrow đầy đủ.
Giới hạn độ sâu CPI
Solana giới hạn độ sâu CPI ở 4 cấp độ. Hướng dẫn cấp cao nhất của giao dịch được tính là độ sâu 0; mỗi lần gọi CPI tăng độ sâu. Ý nghĩa thực tế: swap của Raydium đã sử dụng 1-2 cấp độ CPI (Raydium → SPL Token). Một nhà tích hợp gọi Raydium sử dụng 2. Nếu nhà tích hợp đó được gọi bởi một nhà tích hợp khác, nó là 3. Cấp độ thứ 4 là giới hạn. Hầu hết các thành phần vẫn ở dưới giới hạn này một cách dễ dàng, nhưng lồng sâu (aggregator → router → Raydium → hook) có thể chạm vào nó. Thiết kế phẳng thay vì sâu.Tài khoản còn lại
Khi một hướng dẫn Raydium cần một số lượng tài khoản thay đổi (ví dụ: CLMM swap vượt qua một số lượng tick array không xác định), các tài khoản bổ sung được chuyển dưới dạng remaining accounts — được thêm vào danh sách tài khoản cố định, được diễn giải theo vị trí.SwapV2 của CPMM sử dụng remaining accounts cho các tài khoản bắt buộc bổ sung của các chương trình transfer-hook. Các client tìm nạp các tài khoản cần thiết và thêm chúng:
Cạm bẫy PDA
Seed sai → địa chỉ sai
Một lỗi trong đó các seed ở thứ tự sai, mã hóa sai, hoặc bao gồm/loại trừ một byte bổ sung sẽ im lặng tạo ra một PDA khác. Giao dịch không thành công một cách mơ hồ (chương trình cố gắng đọc một tài khoản không tồn tại). Luôn kiểm tra đơn vị dẫn xuất seed so với các giá trị vàng đã biết.Không lưu trữ bump
Nếu bạn dẫn xuất lại bump trên mỗi giao dịch, bạn sẽ trả tiền tính toán cho vòng lặp dẫn xuất. Lưu trữ canonical bump trong dữ liệu của PDA và đọc nó từ đó.Nhầm lẫn canonical vs non-canonical bump
Non-canonical bumps (nếu ai đó tìm thấy một cái tạo ra ngoài đường cong) được cho phép bởiinvoke_signed nhưng bị từ chối bởi các chương trình của Raydium thông qua assert_eq!(bump, canonical_bump). Nếu ai đó cố gắng yêu sách một PDA với non-canonical bump, tx sẽ không thành công.
Chuyển một PDA làm người ký khi bạn không phải là chương trình sở hữu
Chỉ chương trình có ID trong dẫn xuất PDA mới có thểinvoke_signed với các seed của nó. Nếu bạn cố gắng, runtime sẽ từ chối.
Cạm bẫy CPI
Quên chuyển tiếp remaining_accounts
Nếu hướng dẫn bên ngoài của bạn chuyển các tài khoản transfer-hook trong remaining_accounts nhưng CPI vào Raydium không chuyển tiếp chúng, Raydium sẽ không thành công vì nó không thể tìm thấy các tài khoản hook. Luôn bao gồm with_remaining_accounts trong các CPI cần chúng.
Mismatch cờ writable
Một tài khoản mà hướng dẫn bên ngoài đánh dấu writable cũng phải writable trong lệnh gọi CPI nếu chương trình được gọi dự định ghi vào nó. Mismatch → runtime rejection.Không tính đến rent
CPI đến một chương trình tạo một tài khoản (ví dụ: tạo ATA) yêu cầu người trả phí có đủ SOL cho rent. Các kiểm tra rent không thành công xuất hiện dưới dạng các lỗi mơ hồ.Ví dụ đã làm: tính toán Raydium CPMM PDA
getPoolInfoFromRpc({ poolId }) — nó dẫn xuất các PDA liên quan mà không cần một chuyến đi.
Con trỏ
solana-fundamentals/account-model— cách PDA phù hợp trong mô hình tài khoản.solana-fundamentals/programs-and-anchor— các trợ giúp của Anchor để khai báo PDA.integration-guides/cpi-integration— xây dựng các tích hợp CPI vào Raydium.sdk-api/rust-cpi— các loại Rust CPI của Raydium.
- Solana PDA docs.
- Solana CPI docs.
- Anchor PDA docs và Anchor CPI docs — Anchor không có trang kết hợp.

