# sol-trade-sdk 代码审查报告 审查维度:**逻辑准确性**、**可读性**、**模块化**、**超低延迟**、**代码质量**、**安全性**。 --- ## 1. 代码逻辑准确性 ### 1.1 Instruction 与 IDL / 官方行为 | 模块 | 结论 | 说明 | |------|------|------| | PumpFun buy/sell | ✅ 一致 | 账户顺序、discriminator、track_volume 与 `idl/pump.json` 一致;cashback 时 remainingAccounts 顺序正确 | | PumpSwap buy/sell | ✅ 一致 | 与 `idl/pump_amm.json` 一致;sell cashback 使用 quote_mint ATA | | PDA 推导 | ✅ 一致 | bonding_curve_v2、pool_v2、user_volume_accumulator、creator_vault 等 seeds 与官方一致 | ### 1.2 需修正的逻辑/风格 - **`src/instruction/utils/pumpswap.rs` 约 258、291 行**:`let program_id: &Pubkey = &&accounts::AMM_PROGRAM` 为双重引用,易误导且多余。建议改为 `&accounts::AMM_PROGRAM`。 --- ## 2. 代码可读性 ### 2.1 命名与注释 - 多数模块有中英文注释,instruction 与 IDL 的对应关系有标注。 - **建议**:`src/instruction/pumpfun.rs` 约 259 行 sell 的 discriminator 使用魔法数组 `[51, 230, 133, ...]`,建议改为 `SELL_DISCRIMINATOR` 常量(与 buy 路径一致)。 ### 2.2 错误信息与文案 - **建议**:`src/lib.rs` 中 “Current version only support” 应为 “only supports”;类似拼写/语法可统一检查。 ### 2.3 过长函数 - **建议**:`src/lib.rs` 的 `ensure_wsol_ata` 可拆为「入口 + 重试循环」与「单次尝试 + 结果判断」,便于单测和阅读。 --- ## 3. 模块化 ### 3.1 职责与分层 - **instruction**:按协议分(pumpfun / pumpswap / bonk / raydium_* 等),实现 `InstructionBuilder`,边界清晰。 - **instruction/utils**:PDA、常量、类型、池子解析与上层「组指令」分工明确。 - **swqos**:按提供商分模块,common 放序列化、确认轮询、HTTP 客户端,无循环依赖。 - **结论**:分层合理,模块化良好。 --- ## 4. 超低延迟 ### 4.1 必须改:避免多余 clone | 位置 | 问题 | 建议 | |------|------|------| | `src/instruction/pumpswap.rs` 约 232、429 行 | `Instruction { accounts: accounts.clone(), data }` 对已拥有的 `Vec` 做完整 clone | 改为直接移动:`Instruction { program_id, accounts, data }`,不再 clone | ### 4.2 建议 - 若多路 SWQOS 并发发**同一笔**交易,可在调用方序列化一次,再传 `&[u8]` 给各 client,减少重复 bincode 序列化。 - 热点路径未见不必要的 `Mutex`/`RwLock` 竞争,当前设计可接受。 --- ## 5. 代码质量 ### 5.1 必须改:避免 panic 的 unwrap 以下 PDA 或关键 `Option` 使用 `.unwrap()`,在异常输入下会直接 panic,建议改为 `Result` 并向上传播错误: | 文件 | 行号(约) | 说明 | |------|------------|------| | `src/instruction/pumpfun.rs` | 67, 101, 149, 221, 291, 295 | `get_bonding_curve_pda`、`get_user_volume_accumulator_pda`、`get_bonding_curve_v2_pda` | | `src/instruction/pumpswap.rs` | 184, 198, 385, 407 | `get_user_volume_accumulator_pda`、`get_pool_v2_pda` | | `src/instruction/utils/pumpfun.rs` | 229 | `DEFAULT_CREATOR_VAULT.unwrap()`(LazyLock 未初始化时可能 panic) | | `src/instruction/bonk.rs` | 多处 | `get_pool_pda`、`get_vault_pda`、`params.rpc.as_ref().unwrap()` | | `src/instruction/utils/bonk.rs` | 110–116, 148–152 | `checked_*` 链后 `.unwrap()`,数学假设不成立会 panic | | `src/instruction/raydium_cpmm.rs` | 46, 106, 189, 250 | PDA / 状态相关 unwrap | | `src/instruction/utils/raydium_cpmm.rs` | 83, 85, 141 | `get_vault_pda(...).unwrap()` | **建议**:统一改为 `.ok_or_else(|| anyhow!("..."))?` 或返回 `Result`,在调用链顶层处理错误,避免进程退出。 ### 5.2 建议 - **测试**:为 instruction 构建(或至少 PDA + discriminator/data 布局)增加单元测试,固定输入与预期 bytes/accounts 比对,便于 IDL 升级时回归。 - **错误类型**:`claim_cashback_*` 等返回 `Option`;可考虑统一为 `Result` 并带“无法构建”原因,或在文档中明确 None 的语义。 --- ## 6. 安全性 ### 6.1 必须改:API key 不得写入日志 | 位置 | 问题 | 建议 | |------|------|------| | `src/swqos/astralane_quic.rs` 约 61 行 | `info!(..., "api_key as CN: {}", api_key)` | 移除 api_key 或改为占位(如 `***` / 仅长度) | | `src/swqos/astralane_quic.rs` 约 74 行 | `info!(..., "Connected at {} (api_key: {})", addr, api_key)` | 同上 | ### 6.2 必须改:SkipServerVerification 风险 | 位置 | 问题 | 建议 | |------|------|------| | `src/swqos/astralane_quic.rs` 约 179–181 行 | `with_custom_certificate_verifier(SkipServerVerification)` 完全跳过服务端证书校验 | 1)若服务端提供证书:用 `RootCertStore` 或固定证书做校验;2)若仅 dev/内网:用 feature 或配置限制,并在文档/日志中明确“仅受控环境使用”;3)默认/生产构建建议不跳过校验 | ### 6.3 建议 - **敏感配置**:确保生产环境从环境变量或安全配置读取 API key,并在文档中说明。 - **依赖**:定期执行 `cargo audit` 与依赖升级。 - **unsafe**:`perf/hardware_optimizations.rs`、`realtime_tuning.rs` 中的 `unsafe` 使用范围可控,需保持注释中的安全约定。 --- ## 7. 三库联动与超低延迟检查(sol-trade-sdk / sol-parser-sdk / solana-streamer) ### 7.1 逻辑一致性(已确认) | 检查项 | sol-parser-sdk | solana-streamer | 说明 | |--------|----------------|-----------------|------| | Pump buy 账户数 | 16(fill 用 get(9) 填 creator_vault) | 16,accounts[9]=creator_vault | 与 idl/pumpfun.json 一致 | | Pump sell 账户数 | 14(get(8)=creator_vault) | 14,accounts[8]=creator_vault | 一致 | | PumpSwap buy 17/18 | 指令解析 + fill_buy_accounts get(17)/get(18) | 指令解析 accounts.get(17)/get(18) | coin_creator_vault_ata/authority 正确 | | PumpSwap sell 17/18 | fill_sell_accounts 同左 | 同左 | 一致 | | 填充顺序 | 先 parse(log 或 instruction)→ fill_accounts → push | 指令解析直接写 17/18;无单独 fill 步骤 | 两者均保证事件带齐 creator_vault / coin_creator_vault | | find_instruction_invoke | 选「账户数最多」的 invoke,保证取到 outer buy/sell | N/A(按当前 instruction 解析) | 正确 | ### 7.2 版本化交易账户解析 - **sol-parser-sdk**:`get_instruction_account_getter` 正确支持 versioned tx:先 `account_keys`,再 `loaded_writable_addresses`,再 `loaded_readonly_addresses`,与 Solana 约定一致。 - **solana-streamer**:指令的 `accounts` 为索引,通过 `accounts.get(idx as usize).copied()` 从完整 `accounts: &[Pubkey]` 解析;调用方需传入已包含 loaded 的完整账户列表,否则高索引会得到 `default()`。 ### 7.3 超低延迟相关 | 项目 | 状态 / 建议 | |------|-------------| | solana-streamer 热路径 | 已改为**顺序执行** inner 解析与 swap_data 提取,去掉 `thread::scope` + 双 spawn/join,减少 μs 级开销。 | | sol-parser-sdk | log 与 instruction 并行(rayon::join);fill 仅在有 invoke 时做;`find_instruction_invoke` 为 O(invokes),单程序单 tx 下可接受。 | | sol-trade-sdk | 见上文第 4 节;PumpSwap instruction 构建避免 `accounts.clone()` 已列为必须改。 | ### 7.4 建议 - **solana-streamer**:若 gRPC 上游已提供完整 `accounts`(含 loaded),可避免对每笔 tx 做 `accounts.to_vec()`,仅在需要 resize 时克隆,进一步降低分配。 - **三库**:保持 IDL 与账户索引注释同步(pumpfun.json / pump_amm.json),避免后续扩展时索引错位。 --- ## 8. 汇总:必须改 vs 建议改 ### 必须改(优先处理) | 序号 | 项 | 位置 | |------|----|------| | 1 | 移除 astralane_quic 中 API key 的日志输出 | `src/swqos/astralane_quic.rs` 61、74 行 | | 2 | SkipServerVerification:改为证书校验或仅限 dev 并文档化 | `src/swqos/astralane_quic.rs` 179–181 行 | | 3 | instruction 中 PDA 等 `.unwrap()` 改为 `Result` 并传播错误 | pumpfun.rs、pumpswap.rs、pumpfun/utils、bonk、raydium_cpmm 等 | | 4 | PumpSwap 构建 instruction 时避免 `accounts.clone()`,改为移动 | `src/instruction/pumpswap.rs` 232、429 行 | ### 建议改(可分批) | 序号 | 项 | 位置 | |------|----|------| | 5 | PDA 的 `program_id` 从 `&&AMM_PROGRAM` 改为 `&AMM_PROGRAM` | `src/instruction/utils/pumpswap.rs` 258、291 行 | | 6 | PumpFun sell discriminator 改为命名常量 | `src/instruction/pumpfun.rs` 约 259 行 | | 7 | `ensure_wsol_ata` 拆分;修正 “only support” 等文案 | `src/lib.rs` | | 8 | 为 instruction 构建与 PDA 增加单元测试 | 新建 tests 或模块下 | | 9 | 生产日志用 tracing 替代 println!/eprintln! | `src/swqos/astralane.rs` 等 | --- *报告基于当前仓库与 IDL 的静态阅读;若官方 SDK 或链上程序有未公开变更,建议再与官方实现或链上行为做一次对照验证。*