智能合约安全指南 [特殊字符]️

news2025/3/6 1:26:02

智能合约安全指南 🛡️

在这里插入图片描述

1. 安全基础

1.1 常见漏洞类型

  1. 重入攻击
  2. 整数溢出
  3. 权限控制缺陷
  4. 随机数漏洞
  5. 前后运行攻击
  6. 签名重放

1.2 安全开发原则

  1. 最小权限原则
  2. 检查-生效-交互模式
  3. 状态机安全
  4. 失败保护机制

2. 重入攻击防护

2.1 基本防护模式

contract ReentrancyGuarded {
    bool private locked;
    
    modifier noReentrant() {
        require(!locked, "Reentrant call");
        locked = true;
        _;
        locked = false;
    }
    
    function withdraw() external noReentrant {
        uint256 amount = balances[msg.sender];
        require(amount > 0, "No balance");
        
        balances[msg.sender] = 0; // 先更新状态
        
        (bool success, ) = msg.sender.call{value: amount}("");
        require(success, "Transfer failed");
    }
}

2.2 检查-生效-交互模式

contract CEIPattern {
    mapping(address => uint256) private balances;
    
    function deposit() external payable {
        balances[msg.sender] += msg.value;
    }
    
    function withdraw(uint256 amount) external {
        // 检查
        require(balances[msg.sender] >= amount, "Insufficient balance");
        
        // 生效
        balances[msg.sender] -= amount;
        
        // 交互
        (bool success, ) = msg.sender.call{value: amount}("");
        require(success, "Transfer failed");
    }
}

3. 访问控制

3.1 角色管理

contract RoleBasedAccess {
    using EnumerableSet for EnumerableSet.AddressSet;
    
    mapping(bytes32 => EnumerableSet.AddressSet) private roles;
    
    event RoleGranted(bytes32 indexed role, address indexed account);
    event RoleRevoked(bytes32 indexed role, address indexed account);
    
    modifier onlyRole(bytes32 role) {
        require(hasRole(role, msg.sender), "Unauthorized");
        _;
    }
    
    function hasRole(
        bytes32 role,
        address account
    ) public view returns (bool) {
        return roles[role].contains(account);
    }
    
    function grantRole(
        bytes32 role,
        address account
    ) external onlyRole(DEFAULT_ADMIN_ROLE) {
        if (roles[role].add(account)) {
            emit RoleGranted(role, account);
        }
    }
    
    function revokeRole(
        bytes32 role,
        address account
    ) external onlyRole(DEFAULT_ADMIN_ROLE) {
        if (roles[role].remove(account)) {
            emit RoleRevoked(role, account);
        }
    }
}

3.2 权限代理

contract DelegatedAccess {
    mapping(address => mapping(address => bool)) private delegates;
    
    event DelegateChanged(
        address indexed delegator,
        address indexed delegatee,
        bool status
    );
    
    function setDelegate(address delegatee, bool status) external {
        delegates[msg.sender][delegatee] = status;
        emit DelegateChanged(msg.sender, delegatee, status);
    }
    
    function isDelegate(
        address delegator,
        address delegatee
    ) public view returns (bool) {
        return delegates[delegator][delegatee];
    }
    
    modifier onlyDelegateOrOwner(address owner) {
        require(
            msg.sender == owner || isDelegate(owner, msg.sender),
            "Not authorized"
        );
        _;
    }
}

4. 数据验证

4.1 输入验证

contract InputValidation {
    uint256 public constant MAX_ARRAY_LENGTH = 100;
    uint256 public constant MAX_VALUE = 1e20;
    
    function validateArrayInput(uint256[] calldata data) internal pure {
        require(data.length > 0, "Empty array");
        require(data.length <= MAX_ARRAY_LENGTH, "Array too long");
        
        for (uint i = 0; i < data.length; i++) {
            require(data[i] <= MAX_VALUE, "Value too large");
            if (i > 0) {
                require(data[i] >= data[i-1], "Not sorted");
            }
        }
    }
    
    function validateAddress(address addr) internal pure {
        require(addr != address(0), "Zero address");
        require(addr.code.length == 0, "Contract address not allowed");
    }
}

4.2 状态验证

contract StateValidation {
    enum State { Inactive, Active, Paused, Ended }
    State public currentState;
    
    modifier inState(State requiredState) {
        require(currentState == requiredState, "Invalid state");
        _;
    }
    
    function validateTransition(State newState) internal view {
        if (currentState == State.Inactive) {
            require(newState == State.Active, "Invalid transition");
        } else if (currentState == State.Active) {
            require(
                newState == State.Paused || newState == State.Ended,
                "Invalid transition"
            );
        }
    }
}

5. 签名验证

5.1 EIP712 签名

contract EIP712Verifier {
    bytes32 private DOMAIN_SEPARATOR;
    
    struct EIP712Domain {
        string name;
        string version;
        uint256 chainId;
        address verifyingContract;
    }
    
    constructor(string memory name, string memory version) {
        DOMAIN_SEPARATOR = keccak256(
            abi.encode(
                keccak256(
                    "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
                ),
                keccak256(bytes(name)),
                keccak256(bytes(version)),
                block.chainid,
                address(this)
            )
        );
    }
    
    function verifySignature(
        bytes32 hash,
        bytes memory signature
    ) internal view returns (address) {
        bytes32 digest = keccak256(
            abi.encodePacked("\x19\x01", DOMAIN_SEPARATOR, hash)
        );
        return ecrecover(digest, signature[0], signature[1], signature[2]);
    }
}

5.2 签名重放防护

contract ReplayProtection {
    mapping(bytes32 => bool) private usedSignatures;
    
    function isSignatureUsed(bytes32 hash) public view returns (bool) {
        return usedSignatures[hash];
    }
    
    function markSignatureAsUsed(bytes32 hash) internal {
        require(!usedSignatures[hash], "Signature already used");
        usedSignatures[hash] = true;
    }
    
    function validateSignature(
        bytes32 hash,
        bytes memory signature,
        uint256 deadline
    ) internal view returns (address) {
        require(block.timestamp <= deadline, "Signature expired");
        require(!isSignatureUsed(hash), "Signature already used");
        
        return verifySignature(hash, signature);
    }
}

6. 紧急响应

6.1 紧急停止

contract EmergencyStop {
    bool public stopped;
    address public guardian;
    
    modifier whenNotStopped() {
        require(!stopped, "Contract is stopped");
        _;
    }
    
    modifier whenStopped() {
        require(stopped, "Contract is not stopped");
        _;
    }
    
    function toggleStop() external {
        require(msg.sender == guardian, "Not authorized");
        stopped = !stopped;
        emit EmergencyToggled(stopped);
    }
    
    function emergencyWithdraw() external whenStopped {
        require(msg.sender == guardian, "Not authorized");
        // 执行紧急提款逻辑
    }
}

6.2 漏洞修复

contract UpgradeableSecurityFix {
    address public implementation;
    address public admin;
    
    function upgrade(address newImplementation) external {
        require(msg.sender == admin, "Not authorized");
        require(newImplementation.code.length > 0, "Not a contract");
        
        // 验证新实现是否兼容
        require(
            IUpgradeable(newImplementation).supportsInterface(0x01ffc9a7),
            "Incompatible implementation"
        );
        
        implementation = newImplementation;
        emit Upgraded(newImplementation);
    }
}

7. 审计和测试

7.1 自动化测试

const { expect } = require("chai");
const { ethers } = require("hardhat");

describe("SecurityTests", function() {
    let contract;
    let owner;
    let attacker;
    
    beforeEach(async function() {
        const Contract = await ethers.getContractFactory("SecureContract");
        [owner, attacker] = await ethers.getSigners();
        contract = await Contract.deploy();
    });
    
    it("Should prevent reentrancy attacks", async function() {
        await expect(
            contract.connect(attacker).withdraw()
        ).to.be.revertedWith("Reentrant call");
    });
    
    it("Should validate access control", async function() {
        await expect(
            contract.connect(attacker).adminFunction()
        ).to.be.revertedWith("Not authorized");
    });
});

7.2 形式化验证

/// @notice Invariant: total supply should always equal sum of balances
/// @custom:invariant totalSupply == sum(balances)
contract VerifiedToken {
    mapping(address => uint256) public balances;
    uint256 public totalSupply;
    
    function transfer(address to, uint256 amount) external {
        require(balances[msg.sender] >= amount, "Insufficient balance");
        
        balances[msg.sender] -= amount;
        balances[to] += amount;
        
        assert(balances[msg.sender] <= totalSupply);
        assert(balances[to] <= totalSupply);
    }
}

8. 相关资源

  • 智能合约安全最佳实践
  • OpenZeppelin 安全博客
  • 以太坊安全工具集
  • Slither 静态分析工具
  • MythX 安全平台

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2310281.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Python项目】基于Python的书籍售卖系统

【Python项目】基于Python的书籍售卖系统 技术简介&#xff1a;采用Python技术、MYSQL数据库等实现。 系统简介&#xff1a;书籍售卖系统是一个基于B/S结构的在线图书销售平台&#xff0c;主要分为前台和后台两部分。前台系统功能模块分为&#xff08;1&#xff09;用户中心模…

【Linux】【网络】UDP打洞-->不同子网下的客户端和服务器通信(未成功版)

【Linux】【网络】UDP打洞–>不同子网下的客户端和服务器通信&#xff08;未成功版&#xff09; 上次说基于UDP的打洞程序改了五版一直没有成功&#xff0c;要写一下问题所在&#xff0c;但是我后续又查询了一些资料&#xff0c;成功实现了&#xff0c;这次先写一下未成功的…

(1)udp双向通信(2)udp实现文件复制(3)udp实现聊天室

一.udp双向通信 1.fork进程实现双向通信 【1】head.h 【2】client客户端 &#xff08;1&#xff09;父进程从键盘获取字符串 &#xff08;2&#xff09;输入quit&#xff0c;发送结束子进程信号 &#xff08;3&#xff09;exit退出父进程 &#xff08;1&#xff09;子进程接受…

c高级第五天

1> 在终端提示输入一个成绩&#xff0c;通过shell判断该成绩的等级 [90,100] : A [80, 90) : B [70, 80) : C [60, 70) : D [0, 60) : 不及格 #!/bin/bash# 提示用户输入成绩 read -p "请输入成绩&#xff08;0-100&#xff09;&#xff1a;" score# 判断成…

【JQuery—前端快速入门】JQuery 操作元素

JQuery 操作元素 1. 获取/修改元素内容 三个简单的获取元素的方法&#xff1a; 这三个方法即可以获取元素的内容&#xff0c;又可以设置元素的内容. 有参数时&#xff0c;就进行元素的值设置&#xff0c;没有参数时&#xff0c;就进行元素内容的获取. 接下来&#xff0c;我们需…

标签的ref属性 vue中为什么不用id标记标签

标签的ref属性 vue中为什么不用id标记标签 假设有一对父子组件&#xff0c;如果父组件和子组件中存在id相同的标签&#xff0c;会产生冲突。通过id获取标签会获取到先加载那个标签。 标签的ref属性的用法 在父组件App中&#xff0c;引入了子组件Person。 并使用ref标记了Pe…

7.1.1 计算机网络的组成

文章目录 物理组成功能组成工作方式完整导图 物理组成 计算机网络是将分布在不同地域的计算机组织成系统&#xff0c;便于相互之间资源共享、传递信息。 计算机网络的物理组成包括硬件和软件。硬件中包含主机、前端处理器、连接设备、通信线路。软件中包含协议和应用软件。 功…

IDEA 接入 Deepseek

在本篇文章中&#xff0c;我们将详细介绍如何在 JetBrains IDEA 中使用 Continue 插件接入 DeepSeek&#xff0c;让你的 AI 编程助手更智能&#xff0c;提高开发效率。 一、前置准备 在开始之前&#xff0c;请确保你已经具备以下条件&#xff1a; 安装了 JetBrains IDEA&…

mapbox基础,使用点类型geojson加载symbol符号图层,用于标注文字

👨‍⚕️ 主页: gis分享者 👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍⚕️ 收录于专栏:mapbox 从入门到精通 文章目录 一、🍀前言1.1 ☘️mapboxgl.Map 地图对象1.2 ☘️mapboxgl.Map style属性1.3 ☘️symbol符号图层样式二、🍀使用点类型…

STM32---FreeRTOS中断管理试验

一、实验 实验目的&#xff1a;学会使用FreeRTOS的中断管理 创建两个定时器&#xff0c;一个优先级为4&#xff0c;另一个优先级为6&#xff1b;注意&#xff1a;系统所管理的优先级范围 &#xff1a;5~15 现象&#xff1a;两个定时器每1s&#xff0c;打印一段字符串&#x…

HTTP 状态代码 501 502 问题

问题 单个客户端有时会出现 报错 501 或 502 如下&#xff1a; System.Net.Http.HttpRequestException: Response status code does not indicate success: 501 (Not Implemented) 分析 可以排除 服务器无法处理的问题&#xff08;测试发现 一个客户端报错&#xff0c;不会影响…

visual studio 2022 手工写一个简单的MFC程序

书籍&#xff1a;《Visual C 2017从入门到精通》的2.1.2 MFC方式中2.手工写一个简单的MFC程序 环境&#xff1a;visual studio 2022 内容&#xff1a;手工写一个简单的MFC程序 1.文件->新建->项目 2.根据以下步骤选择Windows桌面向导 3.输入项目名&#xff0c;选择保…

测试用例总结

一、通用测试用例八要素   1、用例编号&#xff1b;    2、测试项目&#xff1b;   3、测试标题&#xff1b; 4、重要级别&#xff1b;    5、预置条件&#xff1b;    6、测试输入&#xff1b;    7、操作步骤&#xff1b;    8、预期输出 二、具体分析通…

vulnhub靶场之【digitalworld.local系列】的development靶机

前言 靶机&#xff1a;digitalworld.local-devt-improved&#xff0c;IP地址为192.168.10.10 攻击&#xff1a;kali&#xff0c;IP地址为192.168.10.6 kali采用VMware虚拟机&#xff0c;靶机选择使用VMware打开文件&#xff0c;都选择桥接网络 这里官方给的有两种方式&…

Select 下拉菜单选项分组

使用<select>元素创建下拉菜单&#xff0c;并使用 <optgroup> 元素对选项进行分组。<optgroup> 元素允许你将相关的 <option> 元素分组在一起&#xff0c;并为每个分组添加一个标签。 <form action"#" method"post"><la…

文件上传漏洞详细利用流程

一、了解基本术语 1、后门 像房子一样&#xff0c;前门后门都可以进出房子&#xff0c;而较之前门&#xff0c;后门更具有隐蔽性。电脑技术中的后门是抽象概念&#xff0c;意指隐蔽性高或不常用的&#xff0c;区别于常规操作所使用的一种出入口。现金网络后门形形色色&#x…

蓝桥与力扣刷题(蓝桥 旋转)

题目&#xff1a;图片旋转是对图片最简单的处理方式之一&#xff0c;在本题中&#xff0c;你需要对图片顺时针旋转 90 度。 我们用一个 nm的二维数组来表示一个图片&#xff0c;例如下面给出一个 34 的 图片的例子&#xff1a; 1 3 5 7 9 8 7 6 3 5 9 7 这个图片顺时针旋转…

transformer架构解析{掩码,(自)注意力机制,多头(自)注意力机制}(含代码)-3

目录 前言 掩码张量 什么是掩码张量 掩码张量的作用 生成掩码张量实现 注意力机制 学习目标 注意力计算规则 注意力和自注意力 注意力机制 注意力机制计算规则的代码实现 多头注意力机制 学习目标 什么是多头注意力机制 多头注意力计算机制的作用 多头注意力机…

使用DiskGenius工具来实现物理机多硬盘虚拟化迁移

使用DiskGenius工具来实现物理机多硬盘虚拟化迁移 概述准备工作注意事项实操过程记录1、Win7虚拟机&#xff0c;安装有两个硬盘&#xff08;硬盘0和硬盘1&#xff09;&#xff0c;各分了一个区&#xff0c;磁盘2是一块未使用的磁盘2、运行DiskGenius程序&#xff0c;记录现有各…

React封装通用Table组件,支持搜索(多条件)、筛选、自动序号、数据量统计等功能。未采用二次封装调整灵活,包含使用文档

封装通用组件 一、封装思想二、react代码三、css代码四、实现效果五、使用文档 BasicTableModal 表格模态框组件1.组件简介2.功能特点3.使用方法基础用法宽度控制示例带筛选功能搜索功能示例自定义单元格渲染 4.API 说明PropsColumn 配置项Filter 配置项 5.注意事项 一、封装思…