You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Solidity中SafeMath库废弃后如何实现日期乘法计算?

Solidity SafeMath废弃问题修复方案

你可以根据是否需要保留0.6.0编译版本,选择以下两种修复方案:


方案1:保留Solidity 0.6.0版本

该方案无需修改原有业务逻辑,仅修复失效的SafeMath导入即可正常编译:

  1. 替换原失效的SafeMath导入语句为适配0.6.0版本的正确引入路径
  2. 代码中所有.add()/.mul()/.sub()语法保持不变
  3. 将代码中的HTML转义字符>统一替换为>

0.6.0版本完整可编译代码:

pragma solidity 0.6.0;
// 导入适配0.6.0版本的OpenZeppelin SafeMath
import 'https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.4.2/contracts/math/SafeMath.sol';

contract Crowdfunding {
    using SafeMath for uint256;

    // 现有项目列表
    Project[] private projects;

    // 新项目创建时触发的事件
    event ProjectStarted(
        address contractAddress,
        address projectStarter,
        string projectTitle,
        string projectDesc,
        uint256 deadline,
        uint256 goalAmount
    );

    /** @dev 创建新项目的方法
      * @param title 项目标题
      * @param description 项目简介
      * @param durationInDays 众筹持续天数
      * @param amountToRaise 众筹目标金额(单位wei)
      */
    function startProject(
        string calldata title,
        string calldata description,
        uint durationInDays,
        uint amountToRaise
    ) external {
        uint raiseUntil = now.add(durationInDays.mul(1 days));
        Project newProject = new Project(msg.sender, title, description, raiseUntil, amountToRaise);
        projects.push(newProject);
        emit ProjectStarted(
            address(newProject),
            msg.sender,
            title,
            description,
            raiseUntil,
            amountToRaise
        );
    }                                                                                                                                   

    /** @dev 获取所有项目合约地址
      * @return 所有项目合约地址列表
      */
    function returnAllProjects() external view returns(Project[] memory){
        return projects;
    }
}

contract Project {
    using SafeMath for uint256;
    
    // 项目状态枚举
    enum State {
        Fundraising,
        Expired,
        Successful
    }

    // 状态变量
    address payable public creator;
    uint public amountGoal; // 最低众筹目标,未达成则所有人可退款
    uint public completeAt;
    uint256 public currentBalance;
    uint public raiseBy;
    string public title;
    string public description;
    State public state = State.Fundraising; // 初始化状态为募资中
    mapping (address => uint) public contributions;

    // 收到捐款时触发的事件
    event FundingReceived(address contributor, uint amount, uint currentTotal);
    // 项目方收到筹款时触发的事件
    event CreatorPaid(address recipient);

    // 检查项目状态的修饰器
    modifier inState(State _state) {
        require(state == _state);
        _;
    }

    // 检查调用方是否为项目发起人的修饰器
    modifier isCreator() {
        require(msg.sender == creator);
        _;
    }

    constructor
    (
        address payable projectStarter,
        string memory projectTitle,
        string memory projectDesc,
        uint fundRaisingDeadline,
        uint goalAmount
    ) public {
        creator = projectStarter;
        title = projectTitle;
        description = projectDesc;
        amountGoal = goalAmount;
        raiseBy = fundRaisingDeadline;
        currentBalance = 0;
    }

    /** @dev 为项目捐款的方法
      */
    function contribute() external inState(State.Fundraising) payable {
        require(msg.sender != creator);
        contributions[msg.sender] = contributions[msg.sender].add(msg.value);
        currentBalance = currentBalance.add(msg.value);
        emit FundingReceived(msg.sender, msg.value, currentBalance);
        checkIfFundingCompleteOrExpired();
    }

    /** @dev 根据条件更新项目状态的方法
      */
    function checkIfFundingCompleteOrExpired() public {
        if (currentBalance >= amountGoal) {
            state = State.Successful;
            payOut();
        } else if (now > raiseBy)  {
            state = State.Expired;
        }
        completeAt = now;
    }

    /** @dev 给项目发起方打款的方法
      */
    function payOut() internal inState(State.Successful) returns (bool) {
        uint256 totalRaised = currentBalance;
        currentBalance = 0;

        if (creator.send(totalRaised)) {
            emit CreatorPaid(creator);
            return true;
        } else {
            currentBalance = totalRaised;
            state = State.Successful;
        }

        return false;
    }

    /** @dev 项目过期后捐款人申请退款的方法
      */
    function getRefund() public inState(State.Expired) returns (bool) {
        require(contributions[msg.sender] > 0);

        uint amountToRefund = contributions[msg.sender];
        contributions[msg.sender] = 0;

        if (!msg.sender.send(amountToRefund)) {
            contributions[msg.sender] = amountToRefund;
            return false;
        } else {
            currentBalance = currentBalance.sub(amountToRefund);
        }

        return true;
    }

    /** @dev 获取项目具体信息的方法
      * @return 返回项目所有基础信息
      */
    function getDetails() public view returns 
    (
        address payable projectStarter,
        string memory projectTitle,
        string memory projectDesc,
        uint256 deadline,
        State currentState,
        uint256 currentAmount,
        uint256 goalAmount
    ) {
        projectStarter = creator;
        projectTitle = title;
        projectDesc = description;
        deadline = raiseBy;
        currentState = state;
        currentAmount = currentBalance;
        goalAmount = amountGoal;
    }
}

方案2:升级到Solidity 0.8+版本(推荐)

Solidity 0.8及以上版本默认内置整数溢出/下溢检查,无需引入第三方SafeMath库,代码更简洁,编译效率更高:

  1. 将编译版本调整为pragma solidity ^0.8.0;
  2. 删除所有SafeMath相关的导入和using SafeMath for uint256;声明
  3. 所有SafeMath方法替换为原生运算符:.add()→+、.mul()→*、.sub()→-
  4. 将已弃用的now关键字替换为等价的block.timestamp
  5. 将代码中的HTML转义字符>统一替换为>

你提到的报错代码行修改后为:

uint raiseUntil = block.timestamp + durationInDays * 1 days;

0.8+版本完整可编译代码:

pragma solidity ^0.8.0;

contract Crowdfunding {
    // 现有项目列表
    Project[] private projects;

    // 新项目创建时触发的事件
    event ProjectStarted(
        address contractAddress,
        address projectStarter,
        string projectTitle,
        string projectDesc,
        uint256 deadline,
        uint256 goalAmount
    );

    /** @dev 创建新项目的方法
      * @param title 项目标题
      * @param description 项目简介
      * @param durationInDays 众筹持续天数
      * @param amountToRaise 众筹目标金额(单位wei)
      */
    function startProject(
        string calldata title,
        string calldata description,
        uint durationInDays,
        uint amountToRaise
    ) external {
        uint raiseUntil = block.timestamp + durationInDays * 1 days;
        Project newProject = new Project(msg.sender, title, description, raiseUntil, amountToRaise);
        projects.push(newProject);
        emit ProjectStarted(
            address(newProject),
            msg.sender,
            title,
            description,
            raiseUntil,
            amountToRaise
        );
    }                                                                                                                                   

    /** @dev 获取所有项目合约地址
      * @return 所有项目合约地址列表
      */
    function returnAllProjects() external view returns(Project[] memory){
        return projects;
    }
}

contract Project {
    // 项目状态枚举
    enum State {
        Fundraising,
        Expired,
        Successful
    }

    // 状态变量
    address payable public creator;
    uint public amountGoal; // 最低众筹目标,未达成则所有人可退款
    uint public completeAt;
    uint256 public currentBalance;
    uint public raiseBy;
    string public title;
    string public description;
    State public state = State.Fundraising; // 初始化状态为募资中
    mapping (address => uint) public contributions;

    // 收到捐款时触发的事件
    event FundingReceived(address contributor, uint amount, uint currentTotal);
    // 项目方收到筹款时触发的事件
    event CreatorPaid(address recipient);

    // 检查项目状态的修饰器
    modifier inState(State _state) {
        require(state == _state);
        _;
    }

    // 检查调用方是否为项目发起人的修饰器
    modifier isCreator() {
        require(msg.sender == creator);
        _;
    }

    constructor
    (
        address payable projectStarter,
        string memory projectTitle,
        string memory projectDesc,
        uint fundRaisingDeadline,
        uint goalAmount
    ) {
        creator = projectStarter;
        title = projectTitle;
        description = projectDesc;
        amountGoal = goalAmount;
        raiseBy = fundRaisingDeadline;
        currentBalance = 0;
    }

    /** @dev 为项目捐款的方法
      */
    function contribute() external inState(State.Fundraising) payable {
        require(msg.sender != creator);
        contributions[msg.sender] += msg.value;
        currentBalance += msg.value;
        emit FundingReceived(msg.sender, msg.value, currentBalance);
        checkIfFundingCompleteOrExpired();
    }

    /** @dev 根据条件更新项目状态的方法
      */
    function checkIfFundingCompleteOrExpired() public {
        if (currentBalance >= amountGoal) {
            state = State.Successful;
            payOut();
        } else if (block.timestamp > raiseBy)  {
            state = State.Expired;
        }
        completeAt = block.timestamp;
    }

    /** @dev 给项目发起方打款的方法
      */
    function payOut() internal inState(State.Successful) returns (bool) {
        uint256 totalRaised = currentBalance;
        currentBalance = 0;

        if (creator.send(totalRaised)) {
            emit CreatorPaid(creator);
            return true;
        } else {
            currentBalance = totalRaised;
            state = State.Successful;
        }

        return false;
    }

    /** @dev 项目过期后捐款人申请退款的方法
      */
    function getRefund() public inState(State.Expired) returns (bool) {
        require(contributions[msg.sender] > 0);

        uint amountToRefund = contributions[msg.sender];
        contributions[msg.sender] = 0;

        if (!payable(msg.sender).send(amountToRefund)) {
            contributions[msg.sender] = amountToRefund;
            return false;
        } else {
            currentBalance -= amountToRefund;
        }

        return true;
    }

    /** @dev 获取项目具体信息的方法
      * @return 返回项目所有基础信息
      */
    function getDetails() public view returns 
    (
        address payable projectStarter,
        string memory projectTitle,
        string memory projectDesc,
        uint256 deadline,
        State currentState,
        uint256 currentAmount,
        uint256 goalAmount
    ) {
        projectStarter = creator;
        projectTitle = title;
        projectDesc = description;
        deadline = raiseBy;
        currentState = state;
        currentAmount = currentBalance;
        goalAmount = amountGoal;
    }
}

内容的提问来源于stack exchange,提问作者Juan Sepulveda

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.18 07:45:07