区块链(25):把 ERC-20 接进托管后,“收到 70”仍要核算
合成订单改用代币后,买方先 approve,托管再 transferFrom。授权额度允许托管在限额内发起转移,不是卖家已经收到 70;approve 成功也不意味着实际 token 转入。区块链(24):fuzz 和 invariant 要围住哪笔资产中的义务单位必须先冻结为某一个 token 的最小单位,否则 UI 把“70.00”与合约整数 70 混用会导致严重错账。 sequenceDiagram participant B as 买方 participant T as ERC20 合约 participant E as 托管合约 B->>T: approve(E, allowance) B->>E: 建立订单并指定资产/数量 E->>T: transferFrom(B, E, amount) T-->>E: 返回值与余额变化需按 token 行为验证 E->>E: 按实际资产和权限记录债权 授权有竞争与遗留额度风险:用户修改额度的交易与第三方支出可能以不同顺序入块。代币还有失败返...
区块链(24):fuzz 和 invariant 要围住哪笔资产
单测覆盖“买方付款、卖家交货、领取成功”,不代表订单状态机能抵御不同调用者、顺序、金额与时间组合。区块链(23):外部调用前后的资产账本怎样保持一致的重入反例提示:不变量应覆盖全局义务,而不只是某个正常路径的返回值。 以原生资产托管为例,令每笔未支付订单的应退款额和所有卖家待领取额构成 liabilities。必要条件是合约可用余额不小于这些义务,并且从来不能由两个终态各登记一次同一笔金额。这里的比较需要明确强制转入等异常余额不会创造可领取债权;只检查 balance == liabilities 可能把合法的额外资产误报为漏洞。非授权地址不应使他人债权下降,错误分支不应悄悄修改订单状态。 flowchart LR SEED[固定 seed 与输入域] --> OPS[随机角色/订单/金额/时序] OPS --> EXEC[部署合约并逐步调用] EXEC --> INV[守恒、单次结算、权限不变量] INV -->|失败| SHRINK[缩小序列、保存重放轨迹] INV -->|通过| LIMIT[仅证明这些输入下未发现反例] 生...
区块链(23):外部调用前后的资产账本怎样保持一致
托管合约为卖家支付 70 时,如果先把资产发给收款合约,再把 claimable 置零,收款方可以在回调里再次进入 withdraw。攻击不需要修改托管源码,只要收款方是有逻辑的外部地址。区块链(22):签名域正确仍会发生业务重放中的签名 nonce 不会自动防住这个跨调用时刻的可重入债权。 sequenceDiagram participant E as 托管合约 participant A as 恶意收款合约 E->>A: 先转出70(错误顺序) A->>E: 回调 withdraw,仍看到 claimable=70 E-->>A: 第二次转出或破坏守恒 Note over E,A: 修复:先校验,再置零债权,再外调 检查—状态更新—交互(CEI)要求在控制权交给外部调用者之前消耗可领取债权;也可考虑可重入锁,但锁不能替代对每条业务状态路径的审计。采用 pull-payment 时,由收款方主动领取可降低订单流转阶段的外部调用数量。若外部调用失败,不能先永久清零余额又默默返回成功;要按策略 revert 使本次状态效...
区块链(22):签名域正确仍会发生业务重放
一个“同意释放订单 70”签名即使通过 EIP-712 的结构化消息校验,也可能被原样提交两次。结构化域通常包括协议名、版本、链 ID、验证合约等;它降低消息与另一应用或网络被误用的风险,却不自动提供业务 nonce、截止时间或撤销表。这些字段及其持久化消费条件由托管应用自己决定。 先修区块链(21):ABI、数据位置与事件各承诺什么与区块链(03):签名证明授权了哪条消息。授权消息至少绑定订单 ID、具体动作、金额、授权者、单次消费标识和期限;合约先检查签名者身份和当前角色、订单状态、域与截止,再在同一状态迁移中消费 nonce,随后安排款项领取。即使签名有效,卖家也不能用买家的签名跨另一个合约、另一笔订单或不同数额提款。 flowchart TD M[domain + typed orderId/action/amount/nonce/deadline] --> S[校验签名者] S --> A[角色和订单状态] A --> D[链/合约/期限正确?] D --> N[nonce 未使用? 原子消费] N --> C[状态变化...
区块链(21):ABI、数据位置与事件各承诺什么
后台拿到订单合约事件 Delivered(orderId) 就把业务表改成“最终交货”,至少跨过了两条未证明的边界:事件来自哪条规范历史,以及现实交货由谁证明。ABI 决定调用输入/输出如何从字节解释,合约 storage 决定持久状态,事件日志便于检索已执行路径;日志不是当前状态的唯一来源,也不会自己监督卖家。 先修区块链(20):教学托管合约先写清谁能推动状态。调用动态数据时,ABI 编码需要指向尾部数据的偏移和长度;calldata 承载外部调用的输入字节,memory 是一次执行的临时区域,storage 承载持久键值。将 storage 引用传给辅助函数可能原地改状态,将其复制到 memory 则不是同一个持久对象;具体 gas、布局和类型尺寸依赖编译器/EVM 目标,不能凭概念图推出物理槽号。 flowchart LR C[calldata: selector + ABI 参数] --> E[函数与内部调用] E --> M[memory: 临时构造] E --> S[storage: 持久订单状态] E --> L[日志: t...
区块链(20):教学托管合约先写清谁能推动状态
合成订单的付款进入教学托管,不应立刻把款转给卖家。区块链(19):revert 以后为什么仍要核算 Gas 与 nonce已经区分提交与执行;合约还需为订单建立明确的状态迁移。买方创建并锁定指定整数单位的款,卖方只能提交交付声明,买方或经约定的裁决者确认后进入待领取,争议或超时按预先冻结的规则退款。交付声明不是现实交付事实,确认者与资金控制权也不能暗中换成部署管理员。 stateDiagram-v2 [*] --> Funded: 买方创建、校验金额 Funded --> Delivered: 卖方声明交付 Delivered --> Claimable: 被授权方确认 Funded --> Refundable: 满足取消条件 Delivered --> Refundable: 到期/裁决规则 Claimable --> Paid: 卖方领取 Refundable --> Refunded: 买方领取 安全不变量包括同一订单只能进入一个终态、账本记载的待领取义务不超过可支配资产、未经授权者不能确认或转移款。活...
区块链(19):revert 以后为什么仍要核算 Gas 与 nonce
交易先经过签名、余额和 nonce 等可接收性检查,执行中还要为每一步消耗 gas。eth_estimateGas 是在给定当时的状态和参数下模拟,后续实际状态、排序和费用环境可能变化;“估算成功”不是“上链执行成功”,模拟时的读数据可能被其他交易改写。区块链(18):EVM 执行后哪些状态进入状态根中的 revert 撤销执行帧的状态效果,不能据此推断发起者完全不付费用。 flowchart TD S[签名与 nonce 有效] --> I[被纳入区块] I --> E{EVM 执行} E -->|成功| C[状态变化 + 用气 + 回执成功] E -->|revert/耗尽 gas| F[业务状态未按预期改变,仍有费用] C --> B[再检查区块与最终性] F --> B EIP-1559 风格费用把协议动态调整的基础费与交易提出的费用上限、小费上限联系起来;基础费按规则处理,不应简单写成全部支付给验证者。应用实际支出要从回执用气量与生效单位价格复算,不能把 maxFeePerGas × gas...
区块链(18):EVM 执行后哪些状态进入状态根
Bitcoin 的输入消耗产生新输出;EVM 的世界状态主要描述账户的 nonce、余额、代码与存储承诺。合约调用携带发送者、目标、value、calldata 与可用 gas,在给定初始状态和规则版本下按确定性执行产生新状态、日志、gas 消耗及成功或失败结果。区块链(17):执行、共识客户端与验证者怎样拼成一个节点的 CL 不替 EL 重演每一步执行,但最终能否认可载荷依赖执行验证。 flowchart LR I[前状态根 + 签名交易 + fork 规则] --> E[EVM: 栈、内存、storage 与调用帧] E --> A[账户余额/nonce/代码/存储变化] A --> R[后状态根] E --> L[日志与回执: 单独承诺对象] E --> X[revert: 调用帧效果撤销,费用另算] 栈用于操作数,内存是调用期间的临时字节区域,storage 是合约持久化的键值空间;一次调用的中间值不自动变成永久链上状态。外部调用可以转移执行控制,必须区分调用失败返回与 revert 传播、内部状态撤销与发送者实际消耗的费...
区块链(17):执行、共识客户端与验证者怎样拼成一个节点
钱包发送交易到执行客户端(EL)的 RPC,不表示共识客户端(CL)已经选它所在的链头。EL 负责 EVM 执行、状态和交易入口;CL 负责共识网络、头选择与最终性判断;验证者客户端持有签名职责并参加提议/投票。两端通过 Engine API 协作:共识端请求构建执行载荷,并让执行端验证收到的载荷,不能只启动其中一个进程就称作完整的 PoS 节点。 先修区块链(16):Gasper 中链头与终局是两次不同判断。在私网里还须冻结执行与共识客户端的兼容版本、chain ID、genesis、fork 时间表、认证材料、验证者存款与网络连接;否则“节点同步”可能只是一端准备就绪,甚至连接了另一条链。Engine API 的认证材料是本地进程凭据,不可纳入博客素材。 sequenceDiagram participant U as 钱包/应用 participant EL as 执行客户端 participant CL as 共识客户端 participant V as 验证者 U->>EL: 提交签名交易 CL->>EL: Engine ...
区块链(16):Gasper 中链头与终局是两次不同判断
买方问“交易在哪个最新区块?”与卖方问“何时不再因正常分叉而撤销?”必须给出两种答复。Gasper 把 LMD-GHOST 风格的叉选择与 Casper FFG 检查点最终性组合起来:最新的有效投票影响当前 head,满足协议门槛并按规则链接的检查点可逐步得到 justified、finalized 状态。head 改变不等于已 finalized 的检查点被常规改写。 flowchart LR V[验证者最新可用投票] --> H[LMD-GHOST: 选择当前 head] H --> T[新交易暂时纳入] V --> J[FFG: 检查点投票] J --> F[justified → finalized] F --> A[应用按预先约定的终局策略兑现] T -.不能自动推出.-> A 最终性不是“有任意大比例在线节点的一条多数意见”,需核对投票源/目标检查点、权重与历史链接;头部选择也不是只找高度最大或只看最近一笔投票。永久不稳定的网络可以阻止足够投票达成最终性,安全性与活性不能互换论证。长期离线的新节点还涉及弱主观...










