05 / 核查带编号的测试计划

Sepolia 手动测试计划

本页是一份可手动执行的检查清单,由配备钱包的人员在 Sepolia 测试网上执行。每个用例都有 T-01 形式的固定编号,可在报告中引用。

开始之前。 本计划针对新版本。仓库的公开清单描述的是 LP 费用为 100 的在用 Sepolia 部署:本计划适用于该部署。对被测版本不适用的用例记为“超出版本范围”,绝不记为“失败”。

所引数值来自 contracts/src/ 下的新版本代码以及 2026 年 9 月 14 日的设计决定。尚无法确认的行为标注为“待测试时确认”。

如何使用本计划

每一节以六列表格列出其用例。最后两列在验收过程中填写。

列 填写内容
用例 固定标识符,T-01 至 T-110
前置条件 开始前必须满足的条件
步骤 按顺序执行的操作
预期结果 代码与决定所规定的结果
观察结果 实际发生的情况,附交易 hash 或读取区块
严重程度 符合预期则留空;否则填阻断、重大、次要或外观
严重程度 标准
阻断 资金损失或被锁、未收取税费、买墙丢失、从本金中支付奖励
重大 行为与来源相悖、缺少应有的拒绝、显示数字错误
次要 不影响链上的显示偏差、提示信息不准确
外观 排版、页面布局、标签文字

按拒绝用例被拒绝的交易,即为成功。 hash 仅表示交易已提交:只有回执说明是否成功。

部分用例不经过界面。 在其当前源码中,dapp 读取在用版本的 ABI,既不提供固定输出订单,也不提供 claimTeam() 或买墙的详细读取。这些用例标注为“直接调用”:使用合约调用工具,针对被测部署清单中的地址执行。

1. 准备

请在第一次交换之前记录以下内容:它们是后续所有比较的参考。

  • 网络:Sepolia,链 ID 11155111。
  • 从清单读取的被测部署地址:代币、hook、PoolManager、poolId、路由器、Lens、V2 注册表、Vault、启动合约;添加 launchpad 后,再加上治理 vault 与 Forge。不要把任何私钥抄入笔记。
  • 固定参数:fee、tickSpacing、LAUNCH_ETH、MIN_POOL_SUPPLY、launchTimestamp、moduleRevision。
  • 初始状态:Lens 的 snapshot()、hook 的 band()、代币的 totalSupply() 与 totalBurned()、pendingFloorEth、pendingAbsorbedTokens、wallCount()、activeWallCount()、teamAccrued、teamPaidCumulative、Vault 的 rewardReserve(),以及读取时的区块号。

除交换金额之外,还需另备测试 ETH:每笔交易都要支付 gas,而且多个用例要求发出会被拒绝的交易,这些交易同样消耗 gas。

用例 前置条件 步骤 预期结果 观察结果 严重程度
T-01 已安装钱包 选择 Sepolia;打开连接被测版本的 dapp 网络被识别;不会提示在其他链上签名
T-02 新账户 通过 Sepolia 水龙头获取测试 ETH 刷新后,钱包与 dapp 中均显示余额
T-03 手边备有清单 将显示的每个地址与清单中的地址比对 身份一致;poolId、fee 与 tickSpacing 相符
T-04 尚未发出任何交换 读取 snapshot() 并记录区块 参考值已记录,区块已标识
T-05 直接调用 读取 hook 的 poolKey() currency0 等于零地址,fee = 100,tickSpacing = 10,hooks 等于该 hook
T-06 V2 注册表可读 读取 moduleRevision() 与各模块地址 记录修订号;若验收期间发生变化,每次签名前都须重新核查

2. 启动与流动性带

池初始化时,hook 将全部存入量放入由 BAND_SALT 标识的单一仓位 [minUsableTick, tickUpper]。tickUpper 是开盘 tick 按间距向下舍入的值,因此该仓位只含 CUBIT。Hook 拒绝低于 MIN_POOL_SUPPLY(即 80 % 供应量)的存入,并销毁舍入零头。

完整启动还会在同一交易中将 20 % 供应量注入 Vault 储备,并执行 0.1 ETH 买入。

用例 前置条件 步骤 预期结果 观察结果 严重程度
T-07 已完成启动,直接调用 读取 band() lower = −887 270;upper 等于开盘 tick 向下舍入到 10 的倍数,FDV 为 3.75 ETH 时为 155 390;流动性不为零
T-08 已知启动交易 读取其事件 BandBootstrapped(lower, upper, liquidity, tokens) 仅发出一次,数值与 band() 一致;tokens 等于存入量减去舍入零头
T-09 启动时无初始买入 在任何交换之前读取 snapshot() 中的 bandEth 与 bandTokens bandEth = 0;bandTokens 等于存入量(允许舍入误差)
T-10 已完成启动,直接调用 读取 token.balanceOf(hook) 为零(第三方直接转账除外):初始化后 hook 不保留任何原始 CUBIT
T-11 直接调用 尝试向池添加流动性 以 ExternalLiquidityForbidden 拒绝:hook 是唯一的流动性提供者
T-12 演练部署 以低于 MIN_POOL_SUPPLY 的存入量初始化池 以 SupplyNotDeposited 拒绝;不建立流动性带
T-13 完整启动 启动交易后读取 Vault 的 rewardReserve() 储备等于 20 % 供应量,即 420 万 CUBIT;无团队分配,无空投
T-14 完整启动 读取启动交易中的部署者买入 买入 0.1 ETH;BuyTaxed 中 3 % 归团队;收到的 CUBIT 可自由转让
T-15 买入已确认,直接调用 根据流动性带的虚拟储备重新计算预期输出 输出与扣除 3 % 税和 LP 费用后的 x·y=k 曲线一致;起初为 1680 万 CUBIT 对 3 ETH 虚拟储备——待测试时确认
T-16 买入后再卖出所买的 CUBIT 在买入前、两者之间及卖出后读取 bandEth bandEth 买入时增加,随后回到接近初始值;它绝不会超过买入实际带入的 ETH

3. 买卖流程

路由器提供 swapExactIn(key, zeroForOne, amountIn, amountOutMin, recipient, deadline) 与 swapExactOut(key, zeroForOne, amountOut, amountInMax, recipient, deadline)。zeroForOne = true 表示用 ETH 买入 CUBIT。

在 dapp 当前源码中,界面只使用固定输入。 用户始终输入所支付的金额;接收数量是只读字段。因此,固定输出流程必须通过直接调用路由器来测试。

买入以 msg.value 发送原生 ETH。卖出发送的 value 为零,并要求向路由器授予 CUBIT 的 ERC-20 授权:界面请求的授权恰为所需金额,从不无限授权,因此更大的卖出需要新的授权。

路由器拒绝部分成交:未被完全消耗的固定输入触发 IncompleteInput,未被完全满足的固定输出触发 InsufficientOutput。由于税费按请求金额计算,撤销交易可以保护用户。

从 dapp 源码读取的界面设置(验收时需核查):滑点容忍度默认 1.0 %,输入限制为两位小数且在 0 至 99.99 区间内;最低接收量以整数计算并向上舍入到 wei;报价新鲜期 30 秒;链上截止时间 = 链上时间戳加 120 秒再减去报价的已存在时长。

用例 前置条件 步骤 预期结果 观察结果 严重程度
T-17 ETH 余额充足 买入小额,例如 0.001 ETH 回执成功;CUBIT 到账;发出 BuyTaxed 事件
T-18 ETH 余额较大 买入大额 回执成功;价格影响体现在报价中,而非税率中
T-19 钱包持有 CUBIT 先授权再卖出 两笔独立交易;收到净 ETH;发出 SellTaxed
T-20 上一笔卖出已确认 卖出大于上一笔的金额 请求新的授权:之前的授权仅针对确切金额
T-21 交换界面已打开 不做改动,查看提供的容忍度 默认值 1.0 %
T-22 交换界面已打开 依次输入 0.005、100 以及一个负值 输入被拒绝,并提示 0–99.99 区间与两位小数限制
T-23 报价新鲜 将容忍度设为可接受的最低值,等待价格变动后签名 以 TooLittleReceived(received, minimum) 拒绝;没有代币损失;界面不提示移除保护
T-24 报价已显示 超过 30 秒不操作,然后尝试签名 报价被视为过期,并在任何签名之前重新计算
T-25 报价即将过期 在过期前一刻签名,并读取传出的截止时间 截止时间等于 120 秒减去报价已存在时长:已存在 30 秒的报价约剩 90 秒
T-26 直接调用 以已过期的截止时间调用 swapExactIn 以 Expired 拒绝;无资金变动
T-27 直接调用 为买入调用 swapExactOut,输入上限留有充足余量 收到确切数量;多余 ETH 在同一交易中退还给调用者
T-28 直接调用 以比所需金额低 1 wei 的输入上限调用 swapExactOut 以 TooMuchRequested(required, maximum) 拒绝
T-29 CUBIT 余额超过流动性带与买墙可回购的数量,例如作为奖励收到的 CUBIT 通过路由器以固定输入卖出该余额 以 IncompleteInput 拒绝;税费随交易一并撤销——待测试时确认
T-30 直接调用 以固定输出请求超过流动性簿可提供的 ETH 以 InsufficientOutput 拒绝;无部分结算
T-31 直接调用 依次发送零金额、零接收方、不一致的 msg.value,以及另一个池 key 分别以 InvalidAmount、ZeroRecipient、WrongValue、WrongPool 拒绝
T-32 兼容的第三方路由器 通过第三方路由买入再卖出 适用 hook 税费
T-33 调用合约或交易批次 在同一交易中先买入再卖出 两个部分分别征税

4. 税费与记账

操作 基数 分配
买入 ETH 毛额部分的 3 % 100 % 归团队份额;分配给买墙的部分明确为零
卖出 输出 ETH 毛额的 15 % 12 % 用于买墙,3 % 归团队

固定输入时,买入税包含在提供的金额中,并向上舍入到 wei。固定输出时,税费叠加在池部分之上,使税费占总额的比例仍为 3 %。

固定输出卖出时,税费为 ceil(sortie × 1500 / 8500):池输出所请求的金额再加上税费。固定输入卖出时,税费为 ceil(brut × 15 %)。分配时,团队份额向下舍入,所有以 wei 计的余数都归买墙。

在 dapp 当前源码中,界面要求先在链上读取这些税率,才允许交换:在税率核实之前,按钮保持等待状态。

用例 前置条件 步骤 预期结果 观察结果 严重程度
T-34 买入已确认 读取 BuyTaxed(ethIn, toFloor, toTeam) toFloor 为零;toTeam 为毛输入的 3 %,向上舍入到 wei
T-35 买入已确认 比较 teamAccrued 的前后数值 增加额等于团队份额
T-36 卖出已确认 读取 SellTaxed(ethOut, toFloor, toTeam) toFloor + toTeam 等于毛额的 15 %;toTeam 为毛额的 3 %;总和精确到 wei
T-37 teamAccrued 不为零,直接调用 从任意账户调用 claimTeam() 资金转往固定的团队地址;发出 TeamPaid(amount, cumulative);teamAccrued 归零
T-38 teamAccrued 为零,直接调用 调用 claimTeam() 调用不回滚,也不转移任何资金
T-39 同一金额先买入再卖出 比较初始 ETH 与最终 ETH(不计 gas) 保留比例接近 0.97 × 0.85 = 0.8245;差异由 LP 费用、价格影响与舍入解释
T-40 两笔规模差异很大的卖出 比较税费占毛额的比例 两种情况下税率均为 15 %;无分档或豁免

5. 自动买墙

每笔卖出时,无论是固定输入还是固定输出,hook 都会先调用 _collectCrossedWalls(),再调用 _placeWall()。它先由近及远清空价格已完全穿越的所有买墙,再将全部待配置的 ETH 放到目标 0.4 × prix courant + 0.6 × prix de lancement,该目标按卖出后的价格计算,并按 tick 舍入。若该目标并非严格高于池 tick(价格等于或低于启动价格时即如此),买墙配置在现价下方 1 %。

被清空的买墙将其 CUBIT 计入 pendingAbsorbedTokens,并将其剩余 ETH(费用与零头)退回 pendingFloorEth。仅被部分消耗的买墙保持原位。只有太小而无法形成流动性的金额,以及价格位于 tick 范围最顶端、价格下方已容不下任何买墙的极端情况,才会让资金在 pendingFloorEth 中等待:卖出绝不会因此被拒绝。随后,CUBIT 路由器在 try/catch 中调用 deliverAbsorbed()。

Lens 的 floorPrice() 参考值表示最近一次获得注资的买墙,而非全局最低价。每穿越一个买墙约耗费 185 000 gas:在单笔交易 16 777 216 gas 的上限内,一笔卖出最多穿越约 88 个买墙。

用例 前置条件 步骤 预期结果 观察结果 严重程度
T-41 价格高于启动价格 卖出,然后读取买墙 发出 WallFunded(id, lower, addedEth, liquidity);在目标 tick 上以待配置的 ETH(含该笔卖出的 12 %)创建或加厚一个买墙(允许舍入误差);pendingFloorEth 只保留未配置的余额
T-42 上一用例的情形 根据卖出后的价格与启动价格重新计算目标 买墙的 lower 与按该价格计算、按 tick 舍入的 40/60 目标一致
T-43 两笔卖出的目标落在同一 tick 读取 wallCount() 与 walls(id) 只有一个买墙:两次 WallFunded 带有相同的 id,流动性增加,不创建新的标识符
T-44 多个买墙位于不同 tick 多次卖出和买入,然后重新读取 walls(id) 每个买墙的 lower 保持不变;没有买墙被移动
T-45 现价下方有有效买墙 卖出一笔会部分消耗但不穿越该买墙的金额 买墙保持有效,同时含 ETH 与 CUBIT;无 WallAbsorbed;pendingAbsorbedTokens 不变
T-46 已被部分消耗的买墙 买入直至价格回到买墙上方 买墙已卖回其 CUBIT 并重新持有 ETH;其标识符与 tick 不变
T-47 有效买墙,通过 CUBIT 路由器卖出 卖出一笔会完全穿越该买墙的金额 在同一交易中先发出 WallAbsorbed(id, cubit, ethRemaining) 与 TokensAbsorbed(amount, pendingAbsorbedTokens),再发出 AbsorbedDelivered(sink, amount) 与 RewardReserveFunded;rewardReserve() 增加这些 CUBIT;pendingAbsorbedTokens 归零;totalSupply() 与 totalBurned() 不变
T-48 价格接近启动价格,40/60 目标不在市场价格下方 卖出一笔可成交的小额,然后读取买墙 卖出成功;发出 WallFunded;买墙配置在卖出后价格下方 1 %,按 tick 舍入;pendingFloorEth 只保留未配置的余额
T-49 T-48 的情形 再次卖出一笔可成交的小额,然后读取 pendingFloorEth 在新价格下方 1 % 发出 WallFunded;pendingFloorEth 只保留舍入零头:各笔卖出之间不会形成积压
T-50 兼容的第三方路由器 通过第三方路由卖出并完全穿越一个买墙,然后从任意账户调用 deliverAbsorbed() 适用税费;发出 TokensAbsorbed,CUBIT 保留在 pendingAbsorbedTokens 中直至该调用,调用时发出 AbsorbedDelivered
T-51 多个买墙已获注资 读取 Lens 的 floorPrice() 与 netFloorPrice(),再在同一区块读取 wallAmountsPage(0, 500) 及后续分页直到 activeWallCount 参考值对应最近注资的买墙,并如实展示为此;买墙中的 CUBIT 等于各页之和加上只计一次的 pendingAbsorbedTokens
T-52 Forge 子项目,买墙被完全穿越 读取子项目 hook 的 absorbedTokenSink(),再读取该笔卖出的事件 目的地等于 Forge 的 governanceVault();发出 AbsorbedDelivered;Deposited(token, from, amount, unlockAt) 批次锁定 30 天
T-106 一笔卖出需穿越大量买墙 估算该笔卖出的 gas,然后发送 每穿越一个买墙约 185 000 gas;超过约 88 个买墙时,卖出超出 16 777 216 gas 并失败,但不造成损失:须拆分卖出
T-107 CUBIT 目的地拒绝接收的演练部署 通过 CUBIT 路由器卖出并穿越一个买墙,然后再次调用 deliverAbsorbed() 卖出成功;CUBIT 保留在 pendingAbsorbedTokens 中;该调用对任何账户开放,只要目的地仍拒绝就会失败

6. mCUBIT Vault

Vault 发放 CUBIT 形式的奖励,仅从 rewardReserve 中支出。奖励为 DAILY_REWARD_BPS = 300,即每个 24 小时周期(REWARD_PERIOD)存款的 3 %,按比例计算并以一个周期为上限:超出部分作废。奖励绝不超过储备余额,也绝不从本金中支付。

每次存款都会对该钱包的整个仓位重启 24 小时锁定(LOCK_DURATION);到期前提款会以 Locked 被拒绝。存款、提款或领取都会先支付已获得的奖励,并重新开始周期。任何账户都可以通过 fundRewardReserve(amount) 为储备注资。到期以链上时间戳判断,而非浏览器时钟。

奖励仅以 CUBIT 形式发放,通过 claimCubit() 领取:Vault 不提供任何 WETH 奖励函数。

用例 前置条件 步骤 预期结果 观察结果 严重程度
T-53 Vault 可用,钱包持有 CUBIT 先授权再存入 发出 Staked(user, amount, unlockAt);unlockAt 等于区块时间戳加 24 小时
T-54 已有仓位 在到期前再次存入 整个仓位的锁定被重启;若已获得奖励不为零,则随 CubitRewardClaimed 支付,周期重新开始
T-55 锁定期内 申请提款 以 Locked 拒绝
T-56 锁定已到期 提取部分存款 部分提款被接受;发出 Withdrawn;先支付已获得的奖励;剩余余额仍保持存入
T-57 存入 1 000 CUBIT,储备充足 12 小时后读取 pendingCubit,24 小时后再次读取 约 15 CUBIT,然后 30 CUBIT
T-58 上一用例的情形 等待 48 小时不领取,然后读取 pendingCubit 仍为 30 CUBIT:第二天的奖励作废
T-59 已获得奖励 调用 claimCubit() CUBIT 已转出;发出 CubitRewardClaimed;rewardReserve 减少所付金额;pendingCubit 归零
T-60 储备很小的演练部署 领取超过储备的奖励 只支付储备余额;储备降为零;本金不受影响
T-61 直接调用 调用 fundRewardReserve(0),再在授权后从任意账户调用 fundRewardReserve(x) 先以 InvalidAmount 拒绝,然后发出 RewardReserveFunded(from, x);rewardReserve 增加 x
T-62 直接调用 在多个时点比较 token.balanceOf(vault) 与 totalStaked + rewardReserve Vault 余额从不低于该总和
T-63 零金额,直接调用 调用 stake(0),再调用 withdraw(0) 两种情况均以 InvalidAmount 拒绝
T-64 Vault 未连接到当前注册表 尝试存款 以 Inactive 拒绝
T-65 仓位已开立 查看显示的锁定时长 以小时显示,由 LOCK_DURATION 推导:24 小时
T-66 已打开 dapp 查找 WETH 奖励流程 无:只提供 CUBIT 奖励

7. Launchpad 治理 vault

治理 vault 接收 Forge 的启动费用(ETH)及 Forge 子项目买墙吸收的代币。每笔存入自其本身到账起锁定 30 天(LOCK_DURATION)。只有部署者可以领取,永久如此且无法转让这项权利,且只能按从旧到新的顺序领取已到期的批次。ETH 记在键 ETH()(零地址)下。验收前请重新阅读被测部署的 ABI。部署者可以用 extendLock 延长所有现有和未来存入的锁定;lockExtension() 只增不减,并加到每个日期上。

从子项目买墙自动发送由 T-52 核查,启动费用的存入由 T-81 核查。T-67 至 T-73 通过直接调用存入测试代币;T-108 领取一笔费用的 ETH。

用例 前置条件 步骤 预期结果 观察结果 严重程度
T-67 测试代币,直接调用 先授权,再调用 deposit(token, amount) 发出 Deposited(token, from, amount, unlockAt);unlockAt 等于区块时间戳加 30 天;held(token) 相应增加
T-68 存入未满 30 天 由部署者调用 claim(token, n) 以 NothingToClaim 拒绝
T-69 批次已解锁 由其他账户调用 claim(token, n) 以 NotDeployer 拒绝
T-70 连续 7 天每天存入一笔 自首笔存入后第 30 天起每天领取 每天释放一个批次,按从旧到新的顺序;最后一批在第七笔存入 30 天后释放;每次领取均发出 Claimed(token, amount, tranches)
T-71 多个批次已解锁 调用 claim(token, 1) 只支付一个批次;下一个批次仍可领取
T-72 通过普通转账发送的代币 调用 lockUntracked(token),然后在没有新转账的情况下再次调用 新批次自第一次调用起锁定 30 天;第二次调用以 NothingToLock 拒绝
T-73 有已锁定和已解锁的批次 读取 claimable(token) 与 locked(token) 可领取金额加已锁定金额等于 held(token)
T-108 T-81 的启动费用已存入超过 30 天 先从另一个账户、再从部署者调用 claim(address(0), 1) 先被 NotDeployer 拒绝,随后 ETH 支付给部署者;发出 Claimed(address(0), amount, 1);held(address(0)) 减少支付的金额
T-109 锁定中的批次 先从另一个账户、再从部署者调用 extendLock(extra) 先被 NotDeployer 拒绝,随后发出 LockExtended(extra, lockExtension);用 tranche(token, i) 读取的每个日期推迟 extra;没有任何函数可以缩短锁定

8. Forge

Forge 是作为未来发布介绍的公开 launchpad。它不属于 CUBIT 的启动:之后会连同其治理 vault 一起添加。添加 launchpad 后,请记录其地址。

任何账户支付准确的费用即可启动子项目。Forge 子项目将其全部供应量存入自己的流动性带,Forge 在构造时接收治理 vault 的地址,且每次启动都将 0.005 ETH 的费用支付给该 vault,由该 vault 保管:启动者永远不会拿回。部署 salt 与启动者绑定。

用例 前置条件 步骤 预期结果 观察结果 严重程度
T-81 Forge 可用,任意账户 以 0.005 ETH 的确切费用启动一个子项目 发出 ChildLaunched(token, hook, launcher, team, fee);子项目的 BandBootstrapped 显示存入量等于其全部供应量(允许舍入误差);治理 vault 发出 Deposited(address(0), forge, fee, unlockAt),其中 unlockAt 等于区块时间戳加 30 天及可能的延长;母 hook 的 pendingFloorEth 不变
T-82 Forge 可用 以错误的 value、空名称、零团队地址或其他模板尝试启动 被拒绝:wrong launch fee、invalid name、invalid team 或 template mismatch
T-110 被另一账户看到的启动 salt 用相同 salt 从第二个账户启动 第一次启动的地址不会被占用:salt 与启动者绑定,若其 hook 地址不具备所需权限,第二次启动会以 child deployment failed 被拒绝

9. 替换与权限

注册表 authority 可以随时、无需等待地替换四个外围地址:Vault、路由器、Lens 与 Forge。每次替换都会发出 ModuleUpdated、递增 moduleRevision,并关闭相应功能,直到团队重新开放:Vault、Momentum 或 Forge;替换路由器不会关闭任何功能。已登记的候选、连接到其他 hook 或其他代币的候选,或已持有质押的候选,都会以 InvalidModule 被拒绝。

Hook 没有任何管理员,任何人都无法暂停交换或买墙机制。团队地址保留永久权力:它获得税费中的团队份额,并替换注册表中的模块、随后将其激活。

用例 前置条件 步骤 预期结果 观察结果 严重程度
T-83 当前 Vault 中有存款与储备 替换 Vault 存入的 CUBIT、奖励储备与期限仍留在旧 Vault;没有资金被移动
T-84 Vault 已被替换 在旧 Vault 上先领取再提款,然后尝试存款 领取和提款仍可用;新存款以 Inactive 被拒绝
T-85 候选已登记,或持有质押 尝试轮换 以 InvalidModule 拒绝
T-86 已完成替换 读取 moduleRevision() 与事件;替换 Vault 后,尝试向新 Vault 存款 修订号已递增;ModuleUpdated(module, previous, current, revision) 数据一致;在 Vault 重新激活之前,存款被 Inactive 拒绝
T-87 已向旧路由器授权 替换路由器,然后尝试卖出 旧授权对新 spender 无效;会请求新的授权
T-88 路由器已替换 通过旧路由器交换 交换仍可进行,适用 hook 税费;dapp 使用新路由器
T-89 直接调用 检查已部署 hook 的 ABI 没有任何函数可以中止交换或买墙机制;hook 没有任何管理员
T-90 直接调用 读取 Lens 的 snapshot(),再在同一区块读取买墙分页 快照只包含市场、流动性带、买墙和账户字段、总供应量、奖励储备、活跃买墙数量、读取区块与最佳买墙,不含买墙总量,其开销也不随买墙数量增长;流通供应量等于 totalSupply 减去买墙中的 CUBIT 和 rewardReserve,持有 CUBIT 等于该供应量减去 bandTokens
T-91 启动后的任意时刻 买入与卖出 交换正常进行:任何账户都无法阻止交换

10. 预期拒绝用例

本表在整个验收过程中作为参考。自动买墙不会给卖出增加拒绝情形:买墙无法配置时资金进入等待,发送失败时 CUBIT 保持等待。

注意事项。 在 dapp 当前源码中,合约错误不会被翻译:链上拒绝可能以原始消息形式显示,并在显示时被截断。对于每个触发的拒绝,请记录显示的确切文字,并判断其是否易于理解。

错误 触发原因 应用应显示的内容
ExternalLiquidityForbidden 第三方添加流动性 无法操作:协议是唯一的流动性提供者
SupplyNotDeposited 以低于 80 % 供应量的存入初始化 无法启动,存入不足
Expired 交易截止时间已过 报价已过期,请重新计算
TooLittleReceived(received, minimum) 输出低于可接受的最低值 触发滑点保护
TooMuchRequested(required, maximum) 输入高于可接受的上限 触发输入上限保护
IncompleteInput 固定输入未被完全消耗 金额超过可用流动性
InsufficientOutput 固定输出未被完全满足 流动性簿无法提供该输出
InvalidAmount, ZeroRecipient, WrongValue, WrongPool 订单参数无效,或向 Vault 发送零金额 输入错误,不显示原始代码
Inactive, Locked Vault 未连接到当前注册表,或到期前提款 模块不可用,或显示解锁日期
NotDeployer, NothingToClaim, NothingToLock, NothingToExtend 第三方向治理 vault 领取或延长、到期前领取、没有新余额时锁定、延长为零 仅限特定角色的操作、无可领取内容、无可锁定内容或无可延长内容
NotAuthority, InvalidModule 第三方请求替换,或候选不兼容 替换被拒绝,并说明原因

纯应用层的拒绝也需记录:报价过期、交换上下文已改变、钱包处于其他链、账户已更换、模块修订已改变、税率尚未核实。

11. 应用

这些用例通过 dapp 执行。所引界面行为来自其源码,在验收时核查。

用例 前置条件 步骤 预期结果 观察结果 严重程度
T-92 Dapp 已打开 逐一浏览选择器中的十种语言 每种语言都显示已翻译的内容,无缺失文字或溢出;产品名称按设计保留英文
T-93 已选择语言 重新加载,然后将窗口缩小到 640 px 以下 所选语言在会话之间保留;低于 640 px 时,选择器只显示国旗
T-94 非英语语言 将首页标题与英文版比较 非英语版本的标题有意缩短;不得溢出或被截断
T-95 约 400 px 的屏幕 浏览每个页面 无水平溢出;宽区域在自身容器内滚动;按钮仍可触及
T-96 窗口宽度在 768 至 1279 px 之间 打开导航 宽度不超过 1279 px 时使用紧凑菜单;导航后菜单自动关闭
T-97 交易已确认 在同一区块将显示的每个金额与链上数值比较 金额一致;显示舍入不改变所签名的金额
T-98 操作准备中 在流程中途切换钱包网络 报价失效,在预期网络之外拒绝签名;按钮先提示切换网络,然后需要再次操作才能交换
T-99 操作准备中 在流程中途切换钱包账户 为新账户重新计算余额、授权与报价;为旧账户准备的签名被拒绝
T-100 已授予授权,交换尚未签名 让模块修订在两者之间发生变化 应用重新验证上下文,不会静默转向新的 spender 继续操作
T-101 RPC 不可用或读取数据陈旧 切断 RPC 访问后观察 状态被标示为未核实,操作被禁用
T-102 交易已发送 跟踪 hash,再跟踪回执 界面区分“已提交”与“成功”;事件可在 Sepolia 区块浏览器上核查
T-103 已触发一次链上拒绝 完整记录显示的文字 消息须让用户能够理解;记录任何原始技术代码或被截断的消息
T-104 中文、韩文和日文 在无法访问外部字体服务的情况下显示这些语言 字符正常显示:字体由网站自身提供
T-105 Proof 页面已打开 查看流动性带、买墙和待配置资金 bandEth、bandTokens、买墙、待配置 ETH 和待发送的 CUBIT 分开显示;任何页面都不展示 ladder、keeper 或买墙销毁

12. 记录表

前面各节的每张表格就是该节的记录表:请随用例逐一填写“观察结果”与“严重程度”两列。观察结果至少应记录交易 hash 或读取区块,再写明所观察到的情况。

附于报告的汇总:

节 用例 符合 偏差 最高严重程度
1. 准备 T-01 至 T-06
2. 启动与流动性带 T-07 至 T-16
3. 买入与卖出 T-17 至 T-33
4. 税费与记账 T-34 至 T-40
5. 自动买墙 T-41 至 T-52、T-106 与 T-107
6. mCUBIT Vault T-53 至 T-66
7. 治理 vault T-67 至 T-73、T-108 及 T-109
8. Forge T-81、T-82 及 T-110
9. 替换与权限 T-83 至 T-91
10. 拒绝用例 通用参考
11. 应用 T-92 至 T-105

偏差应对应用例编号,绝不能只附一张截图。请附上网络、部署地址、区块、hash 以及应用版本。

本计划的局限

本计划描述新版本代码与 2026 年 9 月 14 日决定所规定的内容。它不构成验证:Sepolia 上的验收成功不能替代测试活动。

“待测试时确认”的要点须经观察后补充到本页。

来源: contracts/src/CubitHook.sol, CubitLens.sol, interfaces/ICubitHook.sol, interfaces/ICubitLens.sol, libraries/BandLib.sol, libraries/WallLib.sol, periphery/CubitRouter.sol, CubitV2.sol, CubitVault.sol, CubitGovernanceVault.sol, CubitForge.sol, CubitLaunch.sol、 dapp/src 的当前流程,以及记录于 contracts/docs/REDESIGN_HANDOFF.md 的 2026 年 9 月 14 日设计决定。

CUBIT / 2026 年 9 月 26 日 来源与方法