测试级漏洞合集
简介 拒绝服务 ( Dos - Denial of Service ) 简要概述 DoS 攻击在智能合约中常出现于以下场景: 攻击者通过让某个必要操作持续失败,从而阻止整个合约继续执行关键流程(如奖励分发、批量提款、循环遍历列表等)。 典型示例: 合约在循环中向所有参与者发送 ETH,攻击者故意将自己的 fallback/receive 函数设计为 永远 revert,导致程序在遍历到攻击者地址时整个交易回滚,进而导致奖励分发/提款功能长期瘫痪 易受攻击模式: function distribute() external { for (uint256 i = 0; i < participants.length; i++) { address user = participants[i]; uint256 amount = rewards[user]; // 任意一次 transfer 失败,整个分发流程就会 revert payable(user).transfer(amount); } } 攻击者只需在列表中占据一个位置,即可长期阻塞整个流程。 改进方法 使用 Pull Payment 不再向用户“发送奖励”,而是让用户自己来“领取奖励”,这样单个用户的失败不会影响其他用户 function claim() external { uint256 amount = rewards[msg.sender]; require(amount > 0, "no reward"); // Effects(先修改状态) rewards[msg.sender] = 0; // Interactions(再转账) (bool ok, ) = payable(msg.sender).call{value: amount}(""); require(ok, "send failed"); } CEI 说明: Checks:检查 reward 是否大于 0 Effects:先清零 reward 防止重入 Interactions:最后转账,不会阻塞其他用户 在必须 push 的场景中采用“非阻塞式分发” 避免因为某个地址转账失败而导致整个循环回滚 function distribute() external { for (uint256 i = 0; i < participants.length; i++) { address user = participants[i]; uint256 amount = rewards[user]; (bool ok, ) = payable(user).call{value: amount}(""); if (!ok) { // 可记录失败用户,稍后单独处理 // 不阻塞整体流程 } } } 处理 ETH 不当 ( Mishandling of ETH ) 简要概述 在Solidity智能合约中,“mishandling ETH”错误常指对以太币(ETH)接收和处理的不当管理,尤其在使用delegatecall的批量函数(如提供的batch函数)时。该函数允许通过delegatecall执行多个内部调用,并在同一交易上下文中共享msg.value。主要问题是:如果批量调用包括payable函数(如需要特定msg.value的进入抽奖函数),每个子调用都会看到相同的msg.value,导致合约仅接收一次ETH,但执行多次操作(如多次进入)。例如,在Puppy Raffle审计中,攻击者可通过batch调用多次enterRaffle(每个检查msg.value == entranceFee),仅支付一次费用却进入多次,造成资金损失或不公平。此外,依赖address(this).balance计算费用也易被操纵(如通过selfdestruct强制发送ETH) ...