Blockchain Smart Contracts with Solidity · 课时

使用 SafeMath 进行安全编码

学习使用 SafeMath 等库,防止算术运算中的整数溢出和下溢攻击。

第 3 / 4 课12 个步骤

使用 SafeMath 进行安全编码 是 CoddyKit 上的免费 Blockchain Smart Contracts with Solidity 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Blockchain Smart Contracts with Solidity 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Blockchain Smart Contracts with Solidity 课程共包含 4 节课。

本课时的部分内容尚未翻译,以英文显示。

The Integer Problem

In Solidity, integer types like uint256 have a fixed size. This means they can only store numbers up to a certain maximum value and down to a minimum (usually 0 for unsigned integers).

When an arithmetic operation exceeds these limits, it can lead to critical vulnerabilities called integer overflows and underflows.

Unchecked Math Dangers

Solidity's default arithmetic operations (+, -, *, /) do not automatically check for overflows or underflows. Instead, the number 'wraps around'.

This behavior can be exploited by attackers, leading to incorrect token balances, unexpected contract state, and financial losses.

Overflow in Action

Consider a uint8 variable, which can hold values from 0 to 255. What happens if we try to add 1 to 255? Run this code and call incrementUnsafely(). You'll see the value reset to 0!

/*
  This contract demonstrates an integer overflow.
  A uint8 can only hold values from 0 to 255.
  Adding 1 to 255 will cause it to wrap around to 0.
*/
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract UnsafeCounter {
    uint8 public count = 255; // Max value for uint8

    // Function to increment the counter unsafely
    function incrementUnsafely() public {
        count = count + 1;
    }
}

Underflow Example

Similarly, an underflow occurs when a number goes below its minimum value. For a uint (unsigned integer), the minimum is 0.

If you subtract 1 from 0, it wraps around to the maximum value (255 for uint8, or 2^256 - 1 for uint256).

/*
  This contract demonstrates an integer underflow.
  A uint8 can only hold values from 0 to 255.
  Subtracting 1 from 0 will cause it to wrap around to 255.
*/
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract UnderflowDemo {
    uint8 public value = 0; // Min value for uint8

    // Function to decrement the value unsafely
    function decrementUnsafely() public {
        value = value - 1;
    }
}

Introducing SafeMath

To prevent these critical errors, we use libraries like SafeMath. SafeMath provides functions for arithmetic operations (addition, subtraction, multiplication, division) that revert the transaction if an overflow or underflow would occur.

This ensures your contract's state remains consistent and secure, preventing malicious exploits.

Solidity Libraries Explained

A Solidity Library is a special type of contract that contains reusable code. Unlike regular contracts, libraries are stateless (they don't store data directly) and cannot hold Ether.

  • They are deployed once and their functions are called via DELEGATECALL.
  • This means the library's code runs in the context of the calling contract.
  • Libraries are perfect for shared utility functions like SafeMath.

Integrating SafeMath

To use SafeMath, you typically import it from a trusted source like OpenZeppelin. Then, you tell Solidity to apply SafeMath's functions to a specific integer type using the using A for B; directive.

This makes SafeMath's functions available as member functions on type B.

/*
  This contract demonstrates how to integrate and use SafeMath.
  We're including a simplified mock SafeMath library for demonstration.
*/
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

// A simplified mock SafeMath library for demonstration
library SafeMath {
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");
        return c;
    }
}

contract MySafeContract {
    // Use SafeMath functions for all uint256 variables
    using SafeMath for uint256;

    uint256 public balance = 100;

    function deposit(uint256 amount) public {
        // Now you can call .add() directly on balance
        balance = balance.add(amount);
    }
    
    function getBalance() public view returns (uint256) {
        return balance;
    }
}

Safe Addition in Action

With SafeMath integrated, you use .add() instead of the standard + operator. If the addition would overflow, the transaction will revert, preventing incorrect state changes.

Call safeAdd() with a value like 10. Try calling it with a value that would cause an overflow (e.g., if total was max uint8 and you added 1).

/*
  This contract uses SafeMath for secure addition.
  If the addition causes an overflow, the transaction will revert.
*/
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

library SafeMath {
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");
        return c;
    }
}

contract SafeAdder {
    using SafeMath for uint256;
    uint256 public total = 0;

    function safeAdd(uint256 _value) public {
        total = total.add(_value); // Uses SafeMath.add
    }
}

Safe Subtraction in Action

Similarly, use .sub() for subtraction. This prevents underflows, ensuring that a subtraction operation will revert if the result would be negative (below zero for unsigned integers).

Call safeSubtract() with a value like 10. Try calling it with a value larger than balance (e.g., 101) to see it revert.

/*
  This contract uses SafeMath for secure subtraction.
  If the subtraction causes an underflow, the transaction will revert.
*/
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

library SafeMath {
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a, "SafeMath: subtraction underflow");
        uint256 c = a - b;
        return c;
    }
}

contract SafeSubtractor {
    using SafeMath for uint256;
    uint256 public balance = 100;

    function safeSubtract(uint256 _value) public {
        balance = balance.sub(_value); // Uses SafeMath.sub
    }
}

Multiply, Divide, Modulo

SafeMath also provides .mul(), .div(), and .mod() for multiplication, division, and modulo operations, respectively.

  • .mul() checks for overflow.
  • .div() checks for division by zero and overflow.
  • .mod() checks for division by zero.

Always use these safe versions for critical arithmetic in your contracts.

Quick Check on SafeMath

You've learned about the importance of SafeMath. Let's test your understanding.

Recap: Secure Math

You've learned about the critical vulnerabilities of integer overflows and underflows in Solidity and how SafeMath provides a robust solution.

  • Always use SafeMath (or similar audited libraries) for arithmetic operations on unsigned integers in your smart contracts.
  • This prevents unexpected behavior and protects your contract's integrity.

Keep practicing secure coding! The next lessons will dive deeper into advanced security patterns.

免费开始

用 AI 导师学习 Blockchain Smart Contracts with Solidity — 免费

在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。

课程
12
课程
48

常见问题解答

「使用 SafeMath 进行安全编码」课时是免费的吗?

是的 — 「使用 SafeMath 进行安全编码」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Blockchain Smart Contracts with Solidity 课程的其余内容,请升级到 CoddyKit PRO。 Blockchain Smart Contracts with Solidity 课程共包含 4 节课。

「使用 SafeMath 进行安全编码」这节课中我会学到什么?

学习使用 SafeMath 等库,防止算术运算中的整数溢出和下溢攻击。 你通过在浏览器中直接运行的动手代码来练习 Blockchain Smart Contracts with Solidity,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Blockchain Smart Contracts with Solidity 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Blockchain Smart Contracts with Solidity 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。

「使用 SafeMath 进行安全编码」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Blockchain Smart Contracts with Solidity 课中编写并运行代码吗?

能。每节 Blockchain Smart Contracts with Solidity 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 常见漏洞(重入等)
  2. 访问控制模式
  3. 使用 SafeMath 进行安全编码
  4. 审计、测试与漏洞赏金
← 返回 Blockchain Smart Contracts with Solidity