如果你在 Solana 上跑生产交易,compute unit (CU) 预算是那种"很容易设错、又很难注意到设错了"的参数。设太低,交易会静默失败;设太高,你白白多付 priority fee。我们聊过的大多数机器人操作者都中过这两个里的一个,而且自己没意识到。
这篇我们讲 compute unit 是什么、怎么把预算设对,以及把"调好了的机器人"和"在这一个参数上漏钱的机器人"分开的生产做法。
Compute Unit 是什么
CU 是 Solana 衡量计算工作量的单位。不同指令消耗不同的 CU:
- 简单 SOL 转账:~150 CU
- SPL token 转账:~3,000 CU
- Raydium AMM v4 swap:~30,000-50,000 CU
- Raydium CLMM swap:每过一个 tick ~50,000-100,000 CU
- Jupiter 多跳 swap:变化很大,经常 200,000-400,000 CU
- 复杂 DeFi 组合:500,000+ CU
两个值控制你交易的 CU 行为:
CU limit。 你交易能消耗的最大 CU。默认 200,000。超了交易就失败。
CU price。 每 CU 的 priority fee(单位 microlamports)。默认 0(无优先)。设得越高,这笔交易在打包队列里的优先级越高,也就更可能快速上链。
每笔交易的总 priority fee = cu_limit * cu_price / 1_000_000 / 1_000_000_000 SOL。
怎么把 CU Limit 设对
默认的 200,000 对大多数非平凡交易都是错的。显式设它:
import { ComputeBudgetProgram, Transaction } from "@solana/web3.js";
const tx = new Transaction()
.add(ComputeBudgetProgram.setComputeUnitLimit({ units: 250_000 }))
.add(yourActualInstruction);
合适的值要看交易在做什么。两种确定方法:
方法 1:通过模拟做 profile。
// 不显式设 limit,直接模拟一下
const sim = await connection.simulateTransaction(tx);
console.log("用了 CU:", sim.value.unitsConsumed);
// 把 limit 设为测出来值的 1.2-1.5 倍
对不太依赖链状态的交易很可靠。状态依赖的交易(价格影响路径选择那种),要在有代表性的条件下模拟。
方法 2:用动态 limit。
有些库(Jupiter swap API、特定配置的 Anchor)能帮你算预算。Jupiter 是这样:
const swapResp = await fetch(SWAP_URL, {
method: "POST",
body: JSON.stringify({
quoteResponse: quote,
userPublicKey: wallet.publicKey.toString(),
dynamicComputeUnitLimit: true, // <-- 这个
}),
});
dynamicComputeUnitLimit: true 让 Jupiter 帮你估算这条路由合适的 limit。省得手动 profile。
常见的 CU Limit 错误
留默认 200,000。 很多真实交易需要更多。多跳 swap、复杂 DeFi 组合、CPI 多的程序——这些用默认值都会崩。
为了"以防万一"设太高。 用 150,000 CU 的交易给 1,000,000 limit,意味着你在为白白浪费的 850,000 付 priority fee。
不区分交易类型。 不同路由要不同预算。固定"永远 250,000"对一些交易行,对复杂的就崩。
比需要的 buffer 还大。 按测量值的 1.2-1.5 倍 profile,不是 3 倍 5 倍。
忘了 budget 指令要排在最前。 CU budget 指令必须是交易里最早的几条之一。放在其他指令后面不一定生效。
怎么把 CU Price 设对
这块在Solana Priority Fee 指南讲过了。简单回顾:
- 别用静态值
- 跟着网络条件和预期利润动
- 从 RPC 拿最近的 fee 地板数据
- 边际交易刚好压过地板;高 EV 交易激进给
const tx = new Transaction()
.add(ComputeBudgetProgram.setComputeUnitLimit({ units: 250_000 }))
.add(ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 100_000 }))
.add(yourActualInstruction);
不同用例的 CU 优化
不同负载有不同的 CU 画像。要知道的:
简单 swap(AMM v4)。 ~30,000-50,000 CU。默认预算够用,但你浪费了一些。
集中流动性 swap(CLMM、Whirlpool)。 每过一个 tick 的 CU 不固定。过 2-3 个 tick 的 swap 要 ~80,000-150,000 CU。过更多 tick(波动池子、大单),还要更多。Profile 你自己的实际用量。
Jupiter 多跳路由。 变化很大。用 dynamicComputeUnitLimit: true,别预测。
借贷操作。 借/还/清算因为多个 CPI,常需要 200,000-400,000 CU。
NFT mint。 压缩 NFT mint 便宜(~30,000 CU)。带元数据的标准 NFT mint 重些(~100,000-200,000 CU)。
套利交易。 多指令交易(关 ATA、swap、swap、关 ATA)累加得快。端到端 profile。
CU 不够时失败是什么样
CU 耗尽的失败长这样:
{
err: { InstructionError: [N, "ComputationalBudgetExceeded"] }
}
交易被打包到块里,但跑到一半 CU 用光、被回滚。你为已经消耗的 CU 付了费,但没拿到结果。
生产里的症状:
- "成功"的交易没做你期望的事
- 失败交易集中在某些池子类型上(CLMM 多 tick)
- 波动期失败率更高(每笔 swap 过更多 tick)
看到这些模式,就要在真实条件下模拟一下、审一下 CU 预算。
CU 给太多是什么样
不那么明显,因为没失败:
- priority fee 比预期高
- "为什么这机器人的经济模型比我估算的差?"
- 跨数千笔交易累加,烧的是真 SOL
CU limit 1,000,000、实际用 150,000——你为浪费掉的 850,000 在每笔交易上付 priority fee。在 100 microlamports/CU 时,每笔白付 0.000085 SOL。每天 1000 笔 = ~0.085 SOL/天 = ~31 SOL/年。
这周可以做什么
有生产交易的话:
- 审 CU limit。 你显式设了吗?数值合理吗?
- 每种交易类型都 profile。 用
simulateTransaction测真实消耗。 - limit 设为测量值的 1.2-1.5 倍。 紧到不浪费、松到能扛住最坏情况。
- Jupiter swap 用
dynamicComputeUnitLimit: true。 别猜。 - 算每笔交易的"有效 CU 价格"。 总 priority fee ÷ 实际消耗 CU。这个值你希望它高(说明你没多付)。
- 协议升级后重新 profile。 程序升级时 CU 成本可能变。
常见的 CU Budget 模式
我们见过有效的生产模式:
// 简单 AMM swap
const cuLimit = 100_000;
// CLMM swap(尽量用 dynamic)
const cuLimit = await estimateClmmCu(pool, amount);
// Jupiter swap
// 在 swap API 调用里加 dynamicComputeUnitLimit: true
// 复杂多指令交易
// 通过模拟 profile,设测量值的 1.3 倍
机器人要处理多种交易类型的话,按交易类型参数化 CU limit,不要只用一个固定值。
在生产 CU 负载上试一下 BoltTx
CU 预算调优在你发交易量大的时候更重要——而这恰好是 BoltTx 这些属性最值钱的场景:
- 每笔签名级别的投递遥测——能看每笔交易的 CU 消耗、debug 边缘情况
- 亚秒级确认——失败交易消耗 CU 也消耗时间;更快的确认减少浪费的状态空间
- 原生 Anti-MEV——三明治被夹保护下的交易没有"被竞争机器人捣乱"导致的意外 CU 消耗
- 专属 SWQoS + 优先级连接,你 tip 过的交易能真上链、设的 CU 价格也才有效
import { Connection } from "@solana/web3.js";
const connection = new Connection(
"https://bolttx.io/?api-key=YOUR_API_KEY",
"processed"
);
免费档注册。跑真实的 CU 重型负载,对比每笔上链交易的有效成本。
常见问题
每笔交易最多多少 CU? 1,400,000 CU。CU limit 不能设高于这个值。
能只设 CU price 不设 limit 吗? 能,但通常你两个都想设。不显式设 limit,你用的就是默认 200,000,可能不对。
CU limit 影响交易优先级吗? 不直接。总 priority fee = limit × price。Validator 按总 priority fee 排序,不光看 limit。
设太低会怎样?
交易跑到一半,因为 ComputationalBudgetExceeded 失败。你为已消耗的 CU 付了费。
budget 指令要不要包在签名里? budget 指令是交易的一部分;签名自动覆盖它,不用单独处理。