Type error: Member not found or visible in unit256

Type error: Member not found or visible in unit256

我有一个最初使用 SafeMath 库的众筹平台。由于已弃用,我正在寻找一种解决方法来编译它,但在第 131 行重新混合时出现编译错误:

contributions[msg.sender] = contributions[msg.sender].add(msg.value);

这里有完整的合约代码,这是一个可以创建项目和筹集资金的平台:

// We will be using Solidity version 0.6.0
pragma solidity 0.6.0;
// Importing OpenZeppelin's SafeMath Implementation
//import 'https://github.com/OpenZeppelin/openzeppelin-solidity/contracts/math/SafeMath.sol';
//import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/mocks/SafeMathMock.sol";
//import "@openzeppelin/contracts/utils/math/SafeMath.sol";

contract Crowdfunding {
//    using SafeMath for uint256;

    // List of existing projects
    Project[] private projects;

    // Event that will be emitted whenever a new project is started
    event ProjectStarted(
        address contractAddress,
        address projectStarter,
        string projectTitle,
        string projectDesc,
        uint deadline,
        uint goalAmount
    );

    /** @dev Function to start a new project.
      * @param title Title of the project to be created
      * @param description Brief description about the project
      * @param durationInDays Project deadline in days
      * @param amountToRaise Project goal in wei
      */
    function startProject(
        string calldata title,
        string calldata description,
        uint durationInDays,
        uint amountToRaise
    ) external {
  //      uint raiseUntil = now.add(durationInDays.mul(1 days));
  
     uint durationInSeconds = durationInDays * 1 days;

    // Check that the result of division (inverse operation to multiplication) is the original number.
    // If it's not, throw an exception, because the multiplication overflowed.
    require(durationInSeconds / durationInDays == 1 days, 'Multiplication overflow');

      uint raiseUntil = block.timestamp + durationInSeconds;

     // Check that the result of subtraction (inverse operation to addition) is the original number.
    // If it's not, throw an exception, because the addition overflowed.
    require(raiseUntil - block.timestamp == durationInSeconds, 'Addition overflow'); 
 

    
        Project newProject = new Project(msg.sender, title, description, raiseUntil, amountToRaise);
        projects.push(newProject);
        emit ProjectStarted(
            address(newProject),
            msg.sender,
            title,
            description,
            raiseUntil,
            amountToRaise
        );
    }                                                                                                                                   

    /** @dev Function to get all projects' contract addresses.
      * @return A list of all projects' contract addreses
      */
    function returnAllProjects() external view returns(Project[] memory){
        return projects;
    }
}


contract Project {
// not using SafeMath for uint256;
    
    // Data structures
    enum State {
        Fundraising,
        Expired,
        Successful
    }

    // State variables
    address payable public creator;
    uint public amountGoal; // required to reach at least this much, else everyone gets refund
    uint public completeAt;
    uint256 public currentBalance;
    uint public raiseBy;
    string public title;
    string public description;
    State public state = State.Fundraising; // initialize on create
    mapping (address => uint) public contributions;

    // Event that will be emitted whenever funding will be received
    event FundingReceived(address contributor, uint amount, uint currentTotal);
    // Event that will be emitted whenever the project starter has received the funds
    event CreatorPaid(address recipient);

    // Modifier to check current state
    modifier inState(State _state) {
        require(state == _state);
        _;
    }

    // Modifier to check if the function caller is the project creator
    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 to fund a certain project.
      */
    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 to change the project state depending on conditions.
      */
    function checkIfFundingCompleteOrExpired() public {
        if (currentBalance >= amountGoal) {
            state = State.Successful;
            payOut();
        } else if (now > raiseBy)  {
            state = State.Expired;
        }
        completeAt = now;
    }

    /** @dev Function to give the received funds to project starter.
      */
    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 to retrieve donated amount when a project expires.
      */
    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 Function to get specific information about the project.
      * @return Returns all the project's details
      */
    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;
    }
}

Using X for Y 表达式使用 X 库的函数扩展了 Y 数据类型。

using SafeMath for uint256 的情况下,它允许在 uint256 变量上使用 SafeMath 中定义的函数(例如 add())。

具体来说,SafeMath 中的函数add() 会检查加法运算是否会溢出 256 位无符号整数。如果确实溢出,它会抛出异常。如果它没有溢出,它就是 returns 相加的结果。

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

    return c;
}

您可以使用此代码段获得相同的结果:

uint256 contribution = contributions[msg.sender] + msg.value; // c = a + b
require(contribution >= contributions[msg.sender]); // require(c >= a)
contributions[msg.sender] = contribution; // return c

如果您切换到 Solidity 0.8+,则不需要这样做,因为从 0.8.0 版本开始,Solidity 会自动执行溢出检查并在 overflow/underflow 发生时恢复。所以只使用这个片段就足够了:

// safe in Solidity 0.8+, unsafe in older versions
contributions[msg.sender] += msg.value;

Arithmetic operations revert on underflow and overflow. You can use unchecked { ... } to use the previous wrapping behaviour.

来源:docs