Documentation Index
Fetch the complete documentation index at: https://docs.raydium.io/llms.txt
Use this file to discover all available pages before exploring further.
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 →
PDAs (program-derived addresses) và CPIs (cross-program invocation) là hai primitives làm cho Raydium hoạt động được. PDAs 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 hoạt động của pool authorities và vaults. CPIs cho phép một chương trình gọi chương trình khác — đó là cách Raydium hoán đổi tokens thông qua chương trình SPL Token và cách các integrators kết hợp Raydium vào luồng công việc của riêng họ. Cả hai đều đáng hiểu trước khi đọc mã nguồn của Raydium.
PDAs: địa chỉ không có khóa
Program-Derived Address là một public key mà:- Không nằm trên đường cong ed25519 (không tồn tại khóa riêng cho nó).
- Được dẫn xuất một cách xác định từ một program ID và một tập hợp seeds.
- Có thể được ký bởi chỉ 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 program ID với các seeds, sau đó tìm một byte “bump” để buộc kết quả nằm ngoài đường cong. Byte bump đầu tiên (thường bắt đầu từ 255 và giảm dần) tạo ra một địa chỉ nằm ngoài đường cong sẽ thắng; đây là canonical bump.u64 dưới dạng bytes little-endian. Quy ước của Raydium là một tiền tố có thể đọc được của con người theo sau bởi các định danh duy nhất.
Mẫu PDA của Raydium
PDAs phổ biến trong các chương trình của Raydium:| PDA | Seeds | Program |
|---|---|---|
| AMM authority (AMM v4) | [b"amm authority"] + bump | AMM v4 |
| Pool state (CPMM) | [b"pool", amm_config, mint_a, mint_b] | CPMM |
| Pool vault (CPMM) | [b"pool_vault", pool, mint] | CPMM |
| Authority (CPMM) | [b"vault_and_lp_mint_auth_seed"] | CPMM |
| Pool state (CLMM) | [b"pool", amm_config, mint_0, mint_1] | CLMM |
| Tick array (CLMM) | [b"tick_array", pool, start_tick_index] | CLMM |
| Observation (CLMM) | [b"observation", pool] | CLMM |
| Personal position (CLMM) | [b"position", position_nft_mint] | CLMM |
| Farm state (Farm v6) | [b"pool_farm_state", farm_id] | Farm v6 |
| User ledger (Farm v6) | [b"user_ledger", farm, user] | Farm v6 |
Canonical bump
Mặc dù về nguyên tắc có thể tồn tại nhiều bumps tạo ra các địa chỉ nằm 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 account 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 (chi phí compute lớn):CPIs: 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 instructions của chương trình khác theo cách inline trong một giao dịch duy nhất. Raydium sử dụng CPIs rộng rãi:- Các swap instructions gọi chương trình SPL Token để di chuyển tokens.
- CLMM gọi Metaplex để mint position NFT.
- Pool creation gọi System Program để cấp phát accounts.
- Farm v6 gọi SPL Token để chuyển phần thưởng.
integration-guides/cpi-integration.
invoke vs invoke_signed
Solana runtime cung cấp hai CPI primitives:invoke: gọi chương trình khác; chương trình được gọi sẽ kế thừa các signers từ 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 seeds của PDA và ủy quyền cho chữ ký.
invoke_signed là phép thuật cho phép các chương trình giữ quyền kiểm soát các accounts mà không cần quản lý các khóa riêng.
Ví dụ: Raydium chuyển từ một pool vault
Một pool vault là một Token Account có authority là một PDA của pool program. Để chuyển tokens ra ngoài trong suốt một swap, pool program phải ký tên như PDA đó:invoke_signed được gọi bởi CPMM program, xác minh rằng vault_and_lp_mint_auth_seed + bump dẫn xuất tới địa chỉ của pool_authority khi được băm với program ID của CPMM, và cho phép chữ ký của authority trên token transfer. Không có khóa riêng nào liên quan.
Ví dụ: integrator gọi Raydium CPMM
Một integrator program (ví dụ: một escrow) có thể gọiswap_base_input của Raydium thông qua CPI:
integration-guides/cpi-integration để xem ví dụ escrow đầy đủ.
Giới hạn độ sâu CPI
Solana giới hạn độ sâu CPI ở 4 level. Instruction cấp cao nhất của một giao dịch được tính là depth 0; mỗi CPI invocation tăng depth thêm một. Ý nghĩa thực tế: swap của chính Raydium đã sử dụng 1-2 levels của CPI (Raydium → SPL Token). Một integrator gọi Raydium sử dụng 2. Nếu integrator đó được gọi bởi một integrator khác, đó là 3. Level thứ 4 là giới hạn. Hầu hết các compositions vẫn ở dưới giới hạn này một cách dễ dàng, nhưng nesting sâu (aggregator → router → Raydium → hook) có thể vượt qua nó. Hãy thiết kế flat thay vì deep.Remaining accounts
Khi một Raydium instruction cần một số lượng accounts có thể thay đổi (ví dụ: CLMM swap đi qua một số lượng tick arrays không xác định), các accounts bổ sung được chuyển qua như remaining accounts — được thêm vào danh sách fixed-account, được diễn giải theo vị trí.SwapV2 của CPMM sử dụng remaining accounts cho các transfer-hook programs’ extra required accounts. Clients tìm nạp các accounts cần thiết và thêm chúng:
Những cạm bẫy của PDA
Seeds sai → địa chỉ sai
Một lỗi trong đó các seeds ở thứ tự sai, mã hóa sai, hoặc bao gồm/loại trừ một byte thêm sẽ im lặng tạo ra một PDA khác. Giao dịch sẽ thất bại một cách mơ hồ (chương trình cố gắng đọc một account không tồn tại). Luôn test đơn vị dẫn xuất seed so với các giá trị golden đã biết.Không lưu trữ bump
Nếu bạn tái dẫn xuất bump trên mỗi giao dịch, bạn sẽ phải trả compute 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 off-curve) đượ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 khẳng định một PDA với non-canonical bump, tx sẽ thất bại.
Chuyển một PDA dưới dạng signer 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 của PDA có thểinvoke_signed với các seeds của nó. Nếu bạn cố gắng, runtime sẽ từ chối.
Những cạm bẫy của CPI
Quên chuyển tiếp remaining_accounts
Nếu instruction bên ngoài của bạn chuyển transfer-hook accounts trong remaining_accounts nhưng CPI vào Raydium không chuyển tiếp chúng, Raydium sẽ thất bại vì nó không thể tìm thấy các hook accounts. Luôn bao gồm with_remaining_accounts trong các CPIs cần chúng.
Writable flags mismatch
Một account mà instruction 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 viết vào nó. Mismatch → runtime rejection.Không tính đến rent
CPI tới một chương trình tạo một account (ví dụ: ATA creation) yêu cầu payer có đủ SOL cho rent. Failed rent checks xuất hiện dưới dạng các lỗi mơ hồ.Ví dụ đã làm việc: tính toán PDAs CPMM của Raydium
getPoolInfoFromRpc({ poolId }) — nó dẫn xuất các PDAs liên quan mà không cần một round-trip.
Các con trỏ
solana-fundamentals/account-model— cách PDAs vừa vặn trong mô hình account.solana-fundamentals/programs-and-anchor— các trợ giúp của Anchor để khai báo PDAs.integration-guides/cpi-integration— xây dựng các tích hợp mà CPI vào Raydium.sdk-api/rust-cpi— các loại Rust CPI của Raydium.


