Pulse面向 Monad 的链上高频批量拍卖交易所。每个区块是一轮:同一区块里提交的订单,都以同一个统一价格成交。区块内部的排序赚不到价差,因此没有抢跑,也没有夹击。怎么运作submitOrder(side, tick, amount) 托管资金,并把订单汇总进 64 个固定价格档之一。settle(batch)(区块结束后任何人都可以调用)把 64 个价格档扫描一遍,选出成交量最大的价格。Gas 是常数(约 155–175k),不随订单数量增长。claim(orderId) 按统一价格兑付成交(数量较多的一侧按比例分配),并把没用到的托管资金退回。舍入始终偏向合约,所以合约不可能欠下超过自身持有的资产(已用模糊测试验证)。文档用户指南:给初学者的分步说明(中文)攻击对照:AMM 与 Pulse:演示面板显示什么,以及怎么读团队测试指南:测试清单、已知问题、如何反馈计划:目标、设计、任务状态规模下面是测到的结果,不是承诺:Monad 测试网(web/scripts/stress.ts,在已验证的部署上运行):3.1 秒内确认 600 笔订单,其中单个区块 450 笔。结算该区块需要 172,498 gas;150 笔订单的区块是 154,264 gas。settle 的成本不随订单数增长,因为它是固定的 64 档扫描。Monad 回执会把 gas limit 报成 gasUsed,所以上面的数字来自 eth_estimateGas。forge test --match-contract PulseScaleTest -vv:一个区块 1,000 笔订单,settle 约 188k gas(第一次结算还会初始化批次列表;稳态约 153k)。1,000 笔领取全部兑付,合约始终没有资不抵债。forge test --match-contract PulseInvariantTest:随机的下单、结算、领取序列下,两种代币都保持偿付能力,每个账户的订单列表也保持完整。submitOrders 把多笔订单打进同一笔交易(每笔约 52k gas;单笔冷启动的 submitOrder 约 230k)。为 Monad 做的存储布局:同一价格档的买单和卖单共用一个槽;一个批次的 64 档订单簿从按 128 槽对齐的基址开始,因此一次冷结算只读一页存储。在 Foundry 的 Monad 模式下,这把稳态结算从约 170k 降到约 153k gas。吞吐受限于公共 RPC(约每秒 15 次请求)和付 gas 的 MON,不受限于合约本身。cd web
ORDERS=600 PER_TX=150 npx tsx scripts/stress.ts # 连续发送各批订单,再结算每个区块
npx tsx scripts/keeper.ts # 可选:自动结算每个已结束的批次,并为用户领取(花费上限 MAX_SPEND,默认 0.8 MON)开发forge test -vv配置遵循 Monad 文档(network = "monad",Foundry >= 1.8)。许可证MIT,见 LICENSE。已部署在 Monad 测试网(chainId 10143)所有合约都已在 MonadVision 上验证(Sourcify,完全匹配)。线上应用:https://monadpro.github.io/Pulse/合约地址PulseExchange0x14C0B4328038698B75fdC31D3c19853F8249c29fpMON(基础资产)0xA55556b821966e565102DADee57Fb9Fac297c2A5pUSD(计价资产)0x3e28F0cE40D6Ec7726E424b194B4E2d7F9cb4924SimpleAMM(演示)0xdc97a0C72Bbb08e22d0D04346A80Ff7F0dA7225DAttackLab(演示)0x47B5922CA9FaA65134875110E0c4183363BC0750