《Solidity 简易速速上手小册》第5章:智能合约的安全性(2024 最新版)

在这里插入图片描述

文章目录

  • 5.1 安全性的重要性
    • 5.1.1 基础知识解析
      • 深入理解安全性的多维度影响
      • 智能合约安全的关键要素
    • 5.1.2 重点案例:防止重入攻击
      • 案例 Demo:构建一个防重入的提款合约
      • 案例代码
        • WithdrawContract.sol
      • 测试和验证
      • 拓展功能
    • 5.1.3 拓展案例 1:预防整数溢出
      • 案例 Demo:构建一个防整数溢出的合约
      • 案例代码
        • SafeMathContract.sol
      • 测试和验证
      • 拓展功能
    • 5.1.4 拓展案例 2:防范时间戳操纵
      • 案例 Demo:创建一个防时间戳操纵的合约
      • 案例代码
        • TimelockContract.sol
      • 测试和验证
      • 拓展功能
  • 5.2 常见的安全漏洞和防范
    • 5.2.1 基础知识解析
      • 深入了解常见安全漏洞
      • 重点案例和拓展案例的实施建议
    • 5.2.2 重点案例:防止重入攻击的支付合约
      • 案例 Demo:创建一个安全的支付合约
      • 案例代码
        • SafeWithdrawContract.sol
      • 测试和验证
      • 拓展功能
    • 5.2.3 拓展案例 1:使用 SafeMath 防止整数溢出
      • 案例 Demo:创建一个使用 SafeMath 的合约
      • 案例代码
        • PointsSystem.sol
      • 测试和验证
      • 拓展功能
    • 5.2.4 拓展案例 2:设计时间锁合约
      • 案例 Demo:创建一个基于时间锁的合约
      • 案例代码
        • TimelockContract.sol
      • 测试和验证
      • 拓展功能
  • 5.3 使用模式和最佳实践确保安全
    • 5.3.1 基础知识解析
      • 深入了解安全模式和最佳实践
      • 实践要点
    • 5.3.2 重点案例:实现权限控制
      • 案例 Demo:创建一个具有权限控制的合约
      • 案例代码
        • AccessControlContract.sol
      • 测试和验证
      • 拓展功能
    • 5.3.3 拓展案例 1:实施紧急停止机制
      • 案例 Demo:创建带有紧急停止机制的合约
      • 案例代码
        • EmergencyStopContract.sol
      • 测试和验证
      • 拓展功能
    • 5.3.4 拓展案例 2:使用模式和库
      • 案例 Demo:创建使用安全库的合约
      • 案例代码
        • SafeTokenContract.sol
      • 测试和验证
      • 拓展功能

5.1 安全性的重要性

在智能合约的世界里,安全性就像是一座堡垒的高墙和深沟,它保护着贵重的资产和敏感的数据不受侵害。这一节我们将深入探讨为什么安全性在智能合约设计中占据如此重要的地位。

5.1.1 基础知识解析

在智能合约的开发和维护中,对安全性的重视就像是确保城堡的每一块石头都牢固可靠。不仅是为了防止资产被窃,更是为了维护在这个数字时代中的信誉和可靠性。

深入理解安全性的多维度影响

  1. 经济影响:

    • 漏洞可能导致直接的经济损失,比如资金被盗。
    • 间接成本也很高,包括修复漏洞、法律诉讼费用等。
  2. 信任和声誉:

    • 安全事件会破坏用户对项目的信任,影响项目的长期发展。
    • 一旦声誉受损,重新建立用户信任是一个艰难而漫长的过程。
  3. 合规和法律责任:

    • 合约漏洞可能违反法律法规,特别是在涉及财务和个人数据的场景中。
    • 法律责任可能包括罚款、赔偿甚至刑事责任。

智能合约安全的关键要素

  1. 全面的安全策略:

    • 开发一个包含代码审计、测试和监控的全面安全策略。
    • 定期更新安全措施以应对新出现的威胁。
  2. 安全意识:

    • 开发团队需要具备强烈的安全意识和最新的安全知识。
    • 定期培训和教育可以帮助团队成员识别和防范潜在风险。
  3. 社区协作:

    • 与区块链社区合作,共享知识和资源。
    • 社区审查和漏洞赏金计划可以提高合约的安全性。

安全性在智能合约开发中的重要性不言而喻。它就像是一座城堡的防御工事,不仅保护着财富,更维护着王国的稳定和民众的安宁。在这个充满挑战的数字时代,让我们牢记安全的重要性,共同构建一个更加安全、可靠的区块链世界。

5.1.2 重点案例:防止重入攻击

假设你正在构建一个处理用户提款的智能合约。重入攻击是其中一个常见的安全威胁,攻击者可能利用合约的逻辑漏洞多次提取资金。我们将通过一个案例展示如何防止这种攻击。

案例 Demo:构建一个防重入的提款合约

  1. 规划合约功能:

    • 设计一个合约允许用户存款和提款。
  2. 编写合约代码:

    • 使用状态变量来跟踪每个用户的余额。
    • 在提款逻辑中正确地管理状态变量,以防止重入攻击。
  3. 实现提款逻辑:

    • 在外部调用之前更新合约状态,防止重入。
  4. 部署和测试合约:

    • 在测试网络上部署合约,并尝试进行正常和异常的提款操作。

案例代码

WithdrawContract.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;contract WithdrawContract {mapping(address => uint) public userBalances;function deposit() public payable {userBalances[msg.sender] += msg.value;}function withdraw() public {uint balance = userBalances[msg.sender];require(balance > 0, "No balance to withdraw");userBalances[msg.sender] = 0; // 更新余额,防止重入(bool sent, ) = msg.sender.call{value: balance}("");require(sent, "Failed to send Ether");}
}

WithdrawContract 合约中,我们首先将用户的余额设置为0,然后才执行Ether的发送操作。这样即使攻击者尝试重入,也无法再次提取资金,因为余额已被清零。

测试和验证

  • 部署 WithdrawContract 合约到测试网络。
  • 尝试存款和正常提款操作,验证功能是否正常。
  • 尝试模拟重入攻击,确保合约能够抵御此类攻击。

拓展功能

  • 引入互斥锁: 使用互斥锁机制进一步防止合约在执行过程中被再次调用。
  • 事件记录: 对于每次提款操作,记录事件以便追踪和审计。

通过实现这个防重入的提款合约,你就学会了如何防护合约免受一种常见的安全威胁。这就像是在你的数字金库门口安装了一个先进的锁,确保只有合法的操作能够顺利执行。继续探索,让你的智能合约变得更加坚不可摧!

5.1.3 拓展案例 1:预防整数溢出

在智能合约开发中,整数溢出是一个常见的安全问题。如果没有妥善处理,它可能导致不可预见的行为,比如资金的错误计算。我们将通过一个案例展示如何有效地预防整数溢出。

案例 Demo:构建一个防整数溢出的合约

  1. 设计合约功能:

    • 设计一个合约进行数学运算,比如计算用户的积分。
  2. 编写合约代码:

    • 使用安全的数学操作来防止整数溢出。
  3. 引入安全库:

    • 使用诸如OpenZeppelin的SafeMath库来处理所有数学运算。
  4. 部署和测试合约:

    • 在测试网络上部署合约,并进行数学运算测试,确保没有溢出发生。

案例代码

SafeMathContract.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;import "@openzeppelin/contracts/utils/math/SafeMath.sol";contract SafeMathContract {using SafeMath for uint256;mapping(address => uint256) public userPoints;function increasePoints(address user, uint256 points) public {userPoints[user] = userPoints[user].add(points);}function decreasePoints(address user, uint256 points) public {userPoints[user] = userPoints[user].sub(points, "Decreasing points below zero");}
}

SafeMathContract 合约中,我们利用OpenZeppelin的SafeMath库来确保在增加或减少用户积分时不会发生整数溢出。addsub函数会在溢出时自动抛出异常。

测试和验证

  • 部署 SafeMathContract 合约到测试网络。
  • 尝试正常的积分增加和减少操作,验证功能是否正常。
  • 尝试执行可能导致整数溢出的操作,确保合约能够正确处理此类情况。

拓展功能

  • 更全面的数学操作: 除了加法和减法,也可以使用SafeMath来处理乘法和除法等操作。
  • 事件记录: 对于积分的改变,记录事件以便追踪和审计。

通过实现这个防整数溢出的合约,你就学会了如何使用安全库来避免常见的数学相关安全问题。这就像是在你的数字工具箱中添加了一个精准可靠的计算尺,确保每一次计算都是准确无误的。继续探索,确保你的智能合约在每一个细节上都是安全可靠的!

5.1.4 拓展案例 2:防范时间戳操纵

在智能合约中,时间戳操纵是一个需要警惕的安全问题。攻击者可能利用区块链的时间戳特性来操纵合约行为。我们将通过一个案例来展示如何设计合约以防范时间戳操纵。

案例 Demo:创建一个防时间戳操纵的合约

  1. 设计合约功能:

    • 设计一个合约,比如一个定期释放资金的合约,需要依赖时间来控制释放。
  2. 编写合约代码:

    • 避免完全依赖于block.timestamp(或now)来作为关键逻辑的唯一判断依据。
  3. 引入时间范围:

    • 使用时间范围或者其他状态变量作为辅助判断,减少对精确时间的依赖。
  4. 部署和测试合约:

    • 在测试网络上部署合约,并测试其对时间的处理是否稳健。

案例代码

TimelockContract.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;contract TimelockContract {uint256 public lastReleaseTime;uint256 public releaseInterval;mapping(address => uint256) public balances;constructor(uint256 _interval) {releaseInterval = _interval;lastReleaseTime = block.timestamp;}function deposit() public payable {balances[msg.sender] += msg.value;}function release() public {require(block.timestamp >= lastReleaseTime + releaseInterval, "Release: Not yet time");require(balances[msg.sender] > 0, "Release: No balance to release");lastReleaseTime = block.timestamp; // 更新最后释放时间payable(msg.sender).transfer(balances[msg.sender]);balances[msg.sender] = 0;}
}

TimelockContract 合约中,我们引入了一个时间间隔(releaseInterval)来控制资金的释放。这样做减少了对单个时间点的依赖,从而降低了时间操纵的风险。

测试和验证

  • 部署 TimelockContract 合约到测试网络。
  • 尝试在不同时间进行资金释放操作,验证时间控制是否正确。
  • 测试在时间间隔之前尝试释放资金的情况,确保合约能够正确拒绝这些请求。

拓展功能

  • 动态调整时间间隔: 允许管理员根据需要调整释放资金的时间间隔。
  • 事件记录: 记录每次资金释放的详细信息,包括时间和金额。

通过实现这个防时间戳操纵的合约,你就为合约增加了一层额外的防护。这就像是给你的数字保险箱安装了一个复杂的时间锁,确保只有在正确的时间才能访问里面的资产。继续探索和加强你的智能合约,使其变得更加安全和可靠!

通过深入了解和实践这些安全策略,你将能够为你的智能合约构建一座坚不可摧的防御堡垒。在这个充满挑战和机遇的数字世界中,永远不要低估安全防护的重要性。让我们继续提高警惕,保护我们的数字财富和数据不受威胁!

5.2 常见的安全漏洞和防范

在智能合约的安全防护中,了解和防范常见的安全漏洞就像是给数字堡垒装备上坚固的盾牌和锐利的长矛。这些漏洞如果被忽视,可能成为攻击者利用的突破口。

5.2.1 基础知识解析

在智能合约的世界中,对常见安全漏洞的了解和防范相当于为你的数字城堡构建了一道坚固的防线。这些漏洞如果不被正确处理,就像是城墙上的裂缝,可能导致灾难性的后果。

深入了解常见安全漏洞

  1. 交易顺序依赖(Front Running):

    • 攻击者通过查看未决交易,然后发送具有更高Gas费用的交易来优先执行。
    • 防范方法: 对关键交易引入随机性或使用提交/揭示模式减少可预测性。
  2. Gas Limit和Loops:

    • 循环或复杂计算可能耗尽合约的Gas限制,导致交易失败。
    • 防范方法: 精心设计循环和计算,避免在合约中使用高Gas消耗的操作。
  3. 代理调用(Delegatecall)漏洞:

    • delegatecall用于调用其他合约的函数,但如果使用不当,可能会导致合约状态被意外更改。
    • 防范方法: 谨慎使用delegatecall,确保目标合约的函数逻辑是安全的。

重点案例和拓展案例的实施建议

在应对这些常见的安全漏洞时,需要采取一系列的预防措施:

  • 代码审计和测试: 定期进行代码审计和彻底的测试,以识别潜在的安全漏洞。
  • 使用已验证的模式和库: 利用社区认可的安全模式和库,例如OpenZeppelin提供的合约库。
  • 社区合作: 与区块链社区合作,分享和获取关于安全性的最新信息和技术。
  • 持续监控: 即使合约部署后,也应持续监控其表现,以便及时发现和修复问题。

掌握这些安全知识和技能,就像是为你的数字资产装备上最先进的安全系统。在这个充满挑战的数字世界里,只有不断提高警惕,不懈加强防护,才能确保我们的智能合约安全无虞。

5.2.2 重点案例:防止重入攻击的支付合约

在智能合约开发中,防止重入攻击是一个关键的安全挑战。假设你正在开发一个支付合约,它允许用户存款和提款,我们需要确保这个合约能够防止恶意的重入攻击。

案例 Demo:创建一个安全的支付合约

  1. 设计支付逻辑:

    • 设计一个合约,使用户能够存入资金,并在需要时提取。
  2. 编写防重入合约代码:

    • 在合约中实施安全措施以防止重入攻击。
  3. 使用状态更新防御机制:

    • 在进行任何外部调用之前,先更新合约的状态。
  4. 部署和测试合约:

    • 在测试网络上部署合约,并尝试进行正常和恶意的提款操作。

案例代码

SafeWithdrawContract.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;contract SafeWithdrawContract {mapping(address => uint256) public balances;function deposit() public payable {balances[msg.sender] += msg.value;}function withdraw() public {uint256 balance = balances[msg.sender];require(balance > 0, "No balance to withdraw");balances[msg.sender] = 0; // 首先更新状态(bool success, ) = msg.sender.call{value: balance}("");require(success, "Failed to send Ether");}
}

SafeWithdrawContract 合约中,我们通过首先将用户的余额设置为0,然后再进行Ether转移的方式,来防止重入攻击。这确保了即使攻击者尝试重入,他们也无法再次提取资金,因为余额已经被清零。

测试和验证

  • 在测试网络上部署 SafeWithdrawContract 合约。
  • 进行正常的存款和提款操作,确保合约按预期工作。
  • 尝试模拟重入攻击并验证合约是否能够防御此类攻击。

拓展功能

  • 引入紧急停止机制: 在合约中加入一个紧急停止开关(Circuit Breaker),以便在发现异常行为时停止所有提款操作。
  • 事件记录: 对提款操作进行事件记录,以便于追踪和审计。

通过这个案例,你已经学会了如何设计一个能够抵御重入攻击的安全支付合约。这就像是给你的数字金库安装了一个先进的防盗系统,确保了资金的安全。

5.2.3 拓展案例 1:使用 SafeMath 防止整数溢出

在智能合约开发中,防止整数溢出是保护合约安全的关键步骤。特别是在处理财务相关的逻辑时,整数溢出可能导致严重的安全漏洞。我们将通过一个案例来展示如何使用 SafeMath 库来预防这种情况。

案例 Demo:创建一个使用 SafeMath 的合约

  1. 设计合约逻辑:

    • 设计一个合约,比如一个积分系统,用户可以增加或减少积分。
  2. 引入 SafeMath:

    • 使用 OpenZeppelin 的 SafeMath 库来执行所有数学运算。
  3. 编写合约代码:

    • 在合约中使用 SafeMath 的方法来确保所有的加法、减法操作都不会导致整数溢出。
  4. 部署和测试合约:

    • 在测试网络上部署合约,并尝试进行可能导致溢出的操作。

案例代码

PointsSystem.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;import "@openzeppelin/contracts/utils/math/SafeMath.sol";contract PointsSystem {using SafeMath for uint256;mapping(address => uint256) public points;function addPoints(address user, uint256 _points) public {points[user] = points[user].add(_points);}function subtractPoints(address user, uint256 _points) public {points[user] = points[user].sub(_points, "Subtraction would lead to negative points");}
}

PointsSystem 合约中,我们使用了 SafeMath 的 addsub 函数来处理积分的增加和减少。这些函数会在发生溢出时自动抛出异常,从而保证了积分计算的安全性。

测试和验证

  • 在测试网络上部署 PointsSystem 合约。
  • 尝试对积分进行增加和减少操作,验证功能是否正常。
  • 尝试执行可能导致溢出的操作,确保合约能够正确处理这些情况。

拓展功能

  • 扩展数学运算: 在合约中添加其他类型的安全数学运算,如乘法和除法。
  • 事件记录: 添加事件来记录积分的每次增加或减少,方便追踪和审计。

通过这个案例,你已经学会了如何使用 SafeMath 库来防止智能合约中的整数溢出问题。这就像是给你的数字系统安装了一个自动的安全阀,确保每次运算都在安全的范围内进行。继续实践这些技术,让你的智能合约更加健壮和安全!

5.2.4 拓展案例 2:设计时间锁合约

在智能合约的世界里,设计一个时间锁合约就像是设置一个计时器,确保某些操作只能在特定时间或之后进行。这可以防止因时间戳操纵导致的安全漏洞,特别是在涉及财务操作的场景中。

案例 Demo:创建一个基于时间锁的合约

  1. 确定合约功能:

    • 设计一个合约,例如一个锁定用户资金并在一定时间后才允许提取的合约。
  2. 实现时间锁逻辑:

    • 使用区块时间戳(block.timestamp)结合一个固定的锁定期来控制资金的提取。
  3. 编写合约代码:

    • 编写一个利用时间锁来控制资金提取的合约。
  4. 部署和测试合约:

    • 在测试网络上部署合约,并测试在不同时间点的行为。

案例代码

TimelockContract.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;contract TimelockContract {mapping(address => uint256) public balances;mapping(address => uint256) public lockTime;function deposit() external payable {balances[msg.sender] += msg.value;lockTime[msg.sender] = block.timestamp + 1 weeks; // 锁定1周}function withdraw() external {require(balances[msg.sender] > 0, "No balance to withdraw");require(block.timestamp > lockTime[msg.sender], "Lock time not expired");uint256 amount = balances[msg.sender];balances[msg.sender] = 0;(bool sent, ) = msg.sender.call{value: amount}("");require(sent, "Failed to send Ether");}
}

TimelockContract 合约中,用户存款时设置了一个一周的锁定期。在这段时间内,他们无法提取资金。一旦锁定期过了,用户就可以提取他们的资金。

测试和验证

  • 部署 TimelockContract 合约到测试网络。
  • 尝试存款并在锁定期内和锁定期后进行提款操作,检查合约逻辑是否按预期工作。
  • 验证在锁定期内提款请求被正确拒绝。

拓展功能

  • 可调整的锁定时间: 允许用户在存款时设置不同的锁定时间。
  • 事件记录: 记录存款和提款事件,包括相关的时间信息,以便追踪和审计。

通过实施这个时间锁合约,你就在智能合约中设置了一个有效的时间控制机制。这就像是给你的数字金库设置了一个定时锁,确保资金只能在正确的时间被访问。

通过理解和防范这些常见的安全漏洞,你就能为你的智能合约提供更加坚固的保护。在区块链的世界中,安全永远是第一要务。

5.3 使用模式和最佳实践确保安全

在智能合约的世界中,采用成熟的设计模式和最佳实践就像是为你的数字城堡建立起一道坚固的防线。这些模式和实践能够帮助开发者避免常见的陷阱,确保合约的安全性和可靠性。

5.3.1 基础知识解析

在构建和维护智能合约时,遵循成熟的设计模式和最佳实践是确保其安全性的关键。这些方法像是给你的数字资产制定了一套详尽的保安程序和预防措施。

深入了解安全模式和最佳实践

  1. 状态检查模式(Checks-Effects-Interactions):

    • 遵循这一模式,先进行条件检查(Checks),然后更新状态(Effects),最后与外部合约交互(Interactions)。这有助于防止重入攻击。
  2. 避免过度信任外部合约:

    • 在与外部合约交互时,始终假设它们可能是恶意的。这包括使用call方法发送Ether和依赖外部数据。
  3. 升级和维护模式:

    • 设计可升级的合约,可以在发现漏洞或需要新功能时更新合约代码,而不影响现有的合约状态。
  4. 代码复用和标准化:

    • 利用成熟的、经过审计的智能合约库和标准,如ERC标准,来减少重复的代码编写和降低错误的风险。

实践要点

  1. 持续审计和测试:

    • 定期进行代码审计和全面的测试,以发现并修复潜在的安全漏洞。
  2. 灵活应对安全威胁:

    • 准备好应对新出现的安全威胁,随时更新你的安全策略和实践。
  3. 社区协作与知识共享:

    • 与区块链开发社区保持密切联系,共享和获取最新的安全知识和策略。

通过深入理解和实践这些安全模式和最佳实践,你将能够有效地增强智能合约的安全防护。这些方法和技巧就像是智能合约安全的护城河和高墙,它们共同保卫着你的数字王国免受外部威胁。

5.3.2 重点案例:实现权限控制

在智能合约中实现有效的权限控制就像是为一座城堡设置严格的守卫规则,确保只有授权的人员能够进入特定的区域。这样可以有效防止未授权的访问和操作,保护合约的安全。

案例 Demo:创建一个具有权限控制的合约

  1. 设计合约功能:

    • 设计一个合约,比如一个管理特定资源的合约,只有授权用户才能访问和操作。
  2. 编写合约代码:

    • 利用modifier来创建权限控制逻辑。
    • 设立不同的角色,比如管理员、审计员,并为它们分配不同的权限。
  3. 实现权限检查:

    • 在执行关键功能之前,检查调用者是否具备相应的权限。
  4. 部署和测试合约:

    • 在测试网络上部署合约,并测试不同角色的权限。

案例代码

AccessControlContract.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;contract AccessControlContract {address public admin;mapping(address => bool) public auditors;constructor() {admin = msg.sender;}modifier onlyAdmin() {require(msg.sender == admin, "AccessControl: Only admin can perform this action");_;}modifier onlyAuditor() {require(auditors[msg.sender], "AccessControl: Only auditor can perform this action");_;}function addAuditor(address _auditor) public onlyAdmin {auditors[_auditor] = true;}function removeAuditor(address _auditor) public onlyAdmin {auditors[_auditor] = false;}function auditAction() public onlyAuditor {// 审计员可以执行的操作}
}

AccessControlContract 合约中,我们定义了管理员(admin)和审计员(auditors)两种角色。使用onlyAdminonlyAuditor修饰符来限制特定功能的访问权限。

测试和验证

  • 部署 AccessControlContract 合约到测试网络。
  • 作为管理员添加和移除审计员,检查权限控制是否有效。
  • 尝试以审计员身份执行审计操作,验证权限检查。

拓展功能

  • 引入更多角色和权限: 根据需要,可以增加更多的角色和权限,实现更细粒度的访问控制。
  • 事件记录: 记录关键操作的执行,如角色权限的变更,方便追踪和审计。

通过实现这个具有精细权限控制的合约,你就在智能合约的世界里建立了一套高效的安全管理体系。这就像是为你的数字资产配备了一支训练有素的守卫队伍,确保每一个角落都受到妥善保护。

5.3.3 拓展案例 1:实施紧急停止机制

在智能合约中实施紧急停止机制(又称作“断路器”或“Circuit Breaker”)就像是在建筑中安装紧急疏散通道和火灾警报系统,以便在遇到紧急情况时快速响应和控制风险。

案例 Demo:创建带有紧急停止机制的合约

  1. 定义合约功能:

    • 设计一个处理财务交易的合约,例如一个投资平台。
  2. 实现紧急停止功能:

    • 添加一个可以由管理员触发的紧急停止开关,用于在发现重大漏洞或其他紧急情况时暂停合约操作。
  3. 编写合约代码:

    • 在关键功能中检查紧急停止开关的状态,并根据其状态决定是否执行操作。
  4. 部署和测试合约:

    • 在测试网络上部署合约,并测试紧急停止机制的激活和解除。

案例代码

EmergencyStopContract.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;contract EmergencyStopContract {address public owner;bool public stopped = false;modifier onlyOwner() {require(msg.sender == owner, "Only the owner can perform this action");_;}modifier stopInEmergency() {require(!stopped, "Contract is stopped due to emergency");_;}constructor() {owner = msg.sender;}function toggleContractActive() public onlyOwner {stopped = !stopped;}function deposit() public payable stopInEmergency {// 用户可以在这里存款}function withdraw() public stopInEmergency {// 用户可以在这里提款}
}

EmergencyStopContract 合约中,管理员(通常是合约的部署者)可以通过调用 toggleContractActive 函数来启动或停止合约。stopInEmergency 修饰符用于控制在紧急情况下暂停关键操作,如存款和提款。

测试和验证

  • 部署 EmergencyStopContract 合约到测试网络。
  • 测试正常情况下的存款和提款功能。
  • 模拟紧急情况,激活停止开关,并测试合约是否正确地暂停了操作。
  • 再次切换停止开关,验证合约是否恢复正常操作。

拓展功能

  • 角色基础的控制: 实现基于角色的访问控制,允许不同角色有不同的权限,如只有管理员能触发紧急停止。
  • 事件日志: 记录紧急停止的激活和解除事件,以便于监控和审计。

通过实现这个带有紧急停止机制的合约,你已经为合约安装了一个有效的“安全阀”,它可以在出现风险时立即减少损失。这就像是为你的数字资产提供了一个及时的保护机制,确保在面临突发事件时能够迅速做出反应。

5.3.4 拓展案例 2:使用模式和库

在智能合约开发中,使用经过验证的模式和库就像是在建筑中使用经过测试的材料和技术,它们提供了额外的安全保障。这种做法可以显著降低错误和安全漏洞的风险。

案例 Demo:创建使用安全库的合约

  1. 定义合约需求:

    • 设计一个合约,例如一个代币合约,需要符合特定的标准(如ERC20)。
  2. 选择合适的库:

    • 使用已被广泛测试和认可的库,如OpenZeppelin的合约库,来实现标准。
  3. 编写合约代码:

    • 利用库提供的方法和模式来构建合约,保证安全性和一致性。
  4. 部署和测试合约:

    • 在测试网络上部署合约,并测试其功能以确保符合预期。

案例代码

SafeTokenContract.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;import "@openzeppelin/contracts/token/ERC20/ERC20.sol";contract SafeTokenContract is ERC20 {constructor(uint256 initialSupply) ERC20("SafeToken", "STKN") {_mint(msg.sender, initialSupply);}
}

SafeTokenContract 合约中,我们继承了OpenZeppelin的ERC20标准合约来创建一个符合ERC20标准的代币合约。这样,我们就能利用OpenZeppelin库中预先编写和审核过的代码,确保合约的基本操作符合行业标准,同时减少了安全漏洞的风险。

测试和验证

  • 部署 SafeTokenContract 合约到测试网络。
  • 测试代币的基本功能,如转账、余额查询,确保符合ERC20标准。
  • 验证合约的安全性,确保没有常见的漏洞。

拓展功能

  • 自定义逻辑: 在满足基本标准的基础上,添加合约的自定义逻辑和功能。
  • 合约升级: 考虑合约的可升级性,以便在未来可以添加新功能或修复潜在的问题。

通过在智能合约中使用经过验证的模式和库,你已经为合约的安全性和可靠性增加了一重保障。这就像是在建筑你的数字城堡时,选择了最坚固的石头和最稳健的结构。

通过采用这些模式和最佳实践,你可以为智能合约构建一个坚实的安全基础。就像是为你的数字宝库选择了最合适的保险箱,确保其中的财富得到妥善保护。

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

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

相关文章

Day50 739每日温度 496下一个更大元素I 503下一个更大元素II

739 每日温度 请根据每日 气温 列表,重新生成一个列表。对应位置的输出为:要想观测到更高的气温,至少需要等待的天数。如果气温在这之后都不会升高,请在该位置用 0 来代替。 例如,给定一个列表 temperatures [73, 7…

面试经典150题——生命游戏

​"Push yourself, because no one else is going to do it for you." - Unknown 1. 题目描述 2. 题目分析与解析 2.1 思路一——暴力求解 之所以先暴力求解,是因为我开始也没什么更好的思路,所以就先写一种解决方案,没准写着写…

22-k8s中pod的调度-亲和性affinity

一、概述 在k8s当中,“亲和性”分为三种,节点亲和性、pod亲和性、pod反亲和性; 亲和性分类名称解释说明nodeAffinity节点亲和性通过【节点】标签匹配,用于控制pod调度到哪些node节点上,以及不能调度到哪些node节点上&…

Linux-ls命令

目录 ls:查看目录下文件/文件夹 ls -l:列表显示文件 ls -a:显示所有文件正常情况下‘ . ’开头的文件是隐藏的 ls -la:以列表形式显示所有文件包括隐藏文件 ls -lt:按时间倒序查看文件 ls -R:递归方式…

【git 使用】超级好用的 git reset 和 git revert 功能对比和使用方法

首先你要知道 git 区分暂存区和工作区,如果你用过 sourcetree 你就会知道 git reset 超级好用 git reset 命令用于将当前分支的 HEAD 指针移动到指定的提交,并且可以选择性地修改工作区和暂存区的状态。git reset 命令有几种常用的用法,主要…

突破百度地图Web API的配额限制,实现接口调用自由!

声明 本文章中所有内容仅供学习交流,抓包内容、敏感网址、数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除! 引言 好久没用百度地图开放平台,最近发现平台调整了接口调用的策略,增加了实名认证,…

STM32 USART详细解读(理论知识)

文章目录 前言一、同步传输和异步传输二、UART协议三、UART硬件结构1.波特率,数据位,校验位,停止位设置2.数据发送流程3.数据接收流程4.中断控制 总结 前言 本篇文章来给大家讲解一下STM32中的USART,USART是STM32中非常重要的一个…

QT多线程应用及代码示例

一.多线程的原理和功能 1.多线程(multithreading)是指从软件或者硬件上实现多个线程并发执行的技术。 2.多线程的功能和作用主要包括: 提高程序的并发性和效率:多线程可以同时执行多个任务,不同的线程可以同时读写不…

腾讯云助力酒店IT系统上云,实现出海业务的双重优势

潮起潮涌,随着时代浪潮的翻涌,生活处处可见是巨大的变化,衣食住行都有了更多更大的需求,出门旅游观赏当地风景品尝特色美食的前提是要住好,只有休息好了才有更多的精力去游玩。酒店系统的升级上云让登记变得更加便捷&a…

【机器学习笔记】13 降维

降维概述 维数灾难 维数灾难(Curse of Dimensionality):通常是指在涉及到向量的计算的问题中,随着维数的增加,计算量呈指数倍增长的一种现象。在很多机器学习问题中,训练集中的每条数据经常伴随着上千、甚至上万个特征。要处理这…

【Linux】git操作 - gitee

1.使用 git 命令行 安装 git yum install git 2.使用gitee 注册账户 工作台 - Gitee.com 进入gitee,根据提示注册并登录 新建仓库 仓库名称仓库简介初始换仓库 3.Linux-git操作 进入仓库,选择“克隆/下载” 复制下面的两行命令进行git配置 然后将仓库clo…

教师专业发展的五个阶段

每当人们谈论教师,总会联想到“传道授业解惑”的崇高形象。但教师的专业成长,绝非一蹴而就。今天,就让我们一起探秘教师专业发展的五个阶段,看看一位普通教师是如何历练成为教育行家的。 阶段一:新手摸索期 初入教育行…

走进科学系列之遭遇鬼打墙的OUTLOOK

网管小贾 / sysadm.cc 正值春运,车站里熙熙攘攘、人头攒动。 鲍勃和约瑟夫正在候车室,等待检票。 “嗨!约瑟夫!快来看看,我的电脑出问题了!” “得了吧,马上就要检票上车了,你就不…

调用接口时不时出现 Error: socket hang up

项目场景: 提示:这里简述项目相关背景: 今天采用golang创建了一个http服务,准备对若干接口进行测试。 问题描述 提示:这里描述项目中遇到的问题: 在测试第一个接口时,发现采用postman调用接口…

Ansible yum模块 主要用于软件安装

目录 选项 实例 安装一个tree实例卸载一个 tree 选项 name   #所安装的包的名称 state  #present—>安装, latest—>安装最新的, absent—> 卸载软件。 update_cache  #强制更新yum的缓存 conf_file  #指定远程yum安装时所依赖的配置文件&…

5G车载路由器引领无人驾驶车联网应用

随着无人驾驶技术的不断发展,车联网正逐渐成为实现智能交通的重要组成部分。5G车载路由器将在车联网的应用中起到至关重要的作用,它能够满足无人驾驶应用的低时延、高速率和实时控制等需求,进一步推动无人驾驶车联网技术。 5G路由器具备低时延…

从 AGP 4.1.2 到 7.5.1——XmlParser、GPathResult、QName 过时

新年首发, 去年的问题,今年解决~ 问题 & 排查 1: Task failed with an exception. ----------- * What went wrong: Execution failed for task :app:processCommonReleaseManifest. > org.xml.sax.SAXParseException; lineNumber: 1; columnNu…

【申请体验Sora】OpenAI Red Teaming Network application

网址:https://openai.com/form/red-teaming-network 使用Gmail , 国家选美国 两个问题: Why are you interested in joining the OpenAI Red Teaming Network? I’m eager to experience the powerful allure of Sora, which I believe wi…

postgresql 文件结构(一) 数据库、表对应的文件

1、问题 甲方要求提供数据库数据量大小,由于各个业务数据库共用一个postgres,因此想把每个数据库占用的空间都统计一下。 2、查找物理存储文件目录 如下图所示,可以查询表、库的物理存储文件名称 -- 查询表对应的文件 select oid,relname…

leetcode 01背包问题

典型的01背包问题可以暴力求解,直接将所有可能全部遍历然后挑选符合条件的即可,但这样时间复杂度过高,有2的n次方。 所以我们在这里采用动态规划的方式来做,并且,我们可以采用二维数组或者一维数组来做。 二维数组&a…