为什么 jev-trader 从不调用 eth_estimateGas?Monad 按 gas 上限收费的省钱真相
【免费下载链接】jev-traderOne AI trade decision every Monad block. Jev on Kuru MON-USDC.项目地址: https://gitcode.com/gh_mirrors/je/jev-trader
🤖jev-trader是一个跑在Monad链上的 AI 交易机器人:每 300ms 出块一次,它就在 Kuru 交易所的 MON-USDC 订单簿上下单一次,真实钱包、真实挂单、逐块结算。有趣的是,它的热路径只做2 次 RPC 调用,却从不调用 eth_estimateGas——因为 Monad 的收费规则决定了:gas 估算既省不了钱,还会拖慢你。
先搞懂:Monad 的 gas 到底怎么收?
在大多数 EVM 链上,gas 费用 =实际消耗 gas (gasUsed) × gas 价格。链上交易只花 21,000 gas 就只付 21,000 的钱,所以大家都依赖eth_estimateGas把上限卡得尽可能低。
但 Monad 走了一条不同的路:按 gasLimit(上限)收费,而不是按实际消耗。项目里写得很直白:
- src/market.ts 的注释:
gasLimit x gas price: Monad charges the limit, not gasUsed - README.md:“Monad charges the gas limit, so that is the real cost whether the order lands or not.”
这句话推翻了一切常规 gas 优化:
| 链 | 计费基准 | estimateGas 的作用 |
|---|---|---|
| 常规 EVM 链 | gasUsed(实际消耗) | 有省钱意义 |
| Monad | gasLimit(你声明的上限) | 零意义,纯开销 |
在 Monad 上,把上限估得“更准”一分钱都省不下来;上限设小了交易失败,钱照样照上限扣(src/trader.ts 里charged on reverts too就是这么记账的)。
⏱️ 300ms 预算:热路径只允许两次 RPC 往返
jev-trader 的生死线是:一次决策 + 一笔下单必须塞进一个 300ms 的区块。为此热路径被压缩到极致,每次出块只做两次网络往返(见 README.md “The 300 ms budget”):
eth_call读一次订单簿(公共 RPC 实测约18ms);eth_sendRawTransaction发出已签好的交易,RPC 一收下哈希就返回,不等确认。
实测整个循环 p50 只有100ms(其中 80ms 还是模型的推理占位)。如果每块都加一次eth_estimateGas:
- 多一轮 RPC 往返,直接把 300ms 预算吃穿 → 错过区块(
late块); - 估算结果不稳定、依赖账户状态,失败还得走重试/回退逻辑(项目里专门用 scripts/probe-estimategas.ts 和 scripts/probe-rpc-caps.ts 探测过公共 RPC 上
eth_estimateGas的各种脾气); - 而换来的收益是零——Monad 按上限收费,估算得再准也不省钱。
💡 省钱真相:启动时定死一次上限,之后永不重算
jev-trader 的做法是:把估算从“每块”挪到“启动时一次”。逻辑在 src/market.ts 的initGasLimit():
- 如果你用环境变量
GAS_LIMIT显式指定,直接硬编码; - 否则启动时执行唯一一次
eth_estimateGas(对一笔“无撤单的 post-only 挂单”估算),再加 90,000 余量、放大 1.15 倍,覆盖正常块里会带的一两笔撤单; - 估算失败就用兜底值350,000(实测单独挂单约 282k gas,见 src/config.ts 注释)。
定死之后,每块的交易都是“零预检 RPC”直接签名发送(src/market.ts 的buildTx()注释:“no pre-send RPC, hardcoded gas limit, static type-2 fees”)。这带来两个连锁好处:
- 成本完全可预测:每块 gas 成本 =
gasLimit × (base fee + priority),纯算术。README 事件示例里每块gasMon ≈ 0.0357 MON,启动日志会直接打印“每块多少 MON、每小时多少 MON”,仪表盘逐块展示 gas 花费——对观众而言,成本透明本身就是产品的一部分。 - 静态费用封顶是“免费保险”:交易用 EIP-1559 type-2 格式,
maxFeePerGas设 400 gwei 封顶、priority 固定 2 gwei(src/config.ts)。实际扣费是base + priority,封顶值远高于实际价格时不会多花一分钱,所以热路径上连 gas 价格查询都可以省掉。
📌 从 jev-trader 学到的 4 条高速链 gas 优化清单
- 先确认链的计费基准再谈优化——按 gasUsed 收费的链才值得精细估算,按 gasLimit 收费的链(Monad)估算毫无收益。
- 估算可以存在,但不能在热路径上——jev-trader 不是不用
eth_estimateGas,而是把它挪到启动时跑一次,缓存成固定值。 - 静态 EIP-1559 封顶是零成本冗余——高 maxFee 不花钱,反而省掉每次的价格查询 RPC。
- 成本可预测性本身就是功能——固定上限让每块、每小时的 gas 花费成为纯算术,可以直接展示给用户。
📂 源码指路
| 内容 | 位置 |
|---|---|
| 启动时唯一一次估算 + 兜底值 | src/market.ts |
| 零预检交易构造 | src/market.ts |
| gas 上限/封顶费用配置 | src/config.ts |
| 300ms 预算与 RPC 路径说明 | README.md |
| estimateGas 行为探测脚本 | scripts/probe-estimategas.ts |
| RPC 能力探测脚本 | scripts/probe-rpc-caps.ts |
| 逐块 gas 记账(revert 也照收) | src/trader.ts |
一句话总结:在 Monad 上,gas 优化不是“估得更准”,而是“算得更死”——定死上限、定死费用、热路径零 RPC,省下的不是 gas,是时间和确定性。
【免费下载链接】jev-traderOne AI trade decision every Monad block. Jev on Kuru MON-USDC.项目地址: https://gitcode.com/gh_mirrors/je/jev-trader
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考