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
我有一个最初使用 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