How can I multiply dates in Solidity after Safemath.sol library is deprecated - solidity

I had this piece of code compiling in Solidity 0.6.0 without errors(I'm using Remix). But suddenly SafeMath library got deprecated because it wasn't necessary to import it anymore and I don't know how to fix this line:
uint raiseUntil = now.add(durationInDays.mul(1 days));
where I calculate a future date using the ¨mul¨ function.
I let you all code below. It's the backend of a crowdfunding platform. The raisedUntil variable is the date where the deadline of the crowdfunding project ends.
pragma solidity 0.6.0;
// Importing OpenZeppelin's SafeMath Implementation
import 'https://github.com/OpenZeppelin/openzeppelin-solidity/contracts/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,
uint256 deadline,
uint256 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));
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 {
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;
}
}

You might decide to switch to a newer version of Solidity (current is 0.8.4), where now is deprecated so I already used block.timestamp instead. It's the same thing - now was just its alias.
The SafeMath library checks whether an arithmetic operation (such as multiplication or addition) on two unsigned integers would overflow/underflow. If it would, it throws an exception. If it wouldn't, it performs the arithmetic operation. Since Solidity 0.8 this is done automatically and SafeMath is not needed, so another reason to use the current version.
In Solidity 0.8 and newer, if this would overflow, it would throw an exception automatically
uint raiseUntil = block.timestamp + durationInDays * 1 days;
In older versions, you'll need to check for the possible overflow yourself and throw the exception from your code (the same behavior as SafeMath would do).
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');
Integer overflow/underflow is one of the most common security vulnerabilities in smart contracts. If your startProject() function was vulnerable, it would only allow to start a project with a deadline in the past. But in other implementations it can have more serious consequences. For example if an attacker exploits this vulnerability on a token contract, it could allow them to spend more tokens than they own.

Related

Getting Block Hash of another contract

I've seen some problems with calling functions from other contracts but I believe my problem is fairly genuine to demand a separate question if only to be negated in its possibility.
So I am trying to call a contract within another contract. Is it possible to get the blockhash of a particular block number of the callee contract within my caller? If so how?
Every syntax I've attempted fails for some reason.
Contract A
enter code here
contract DiceGame {
uint256 public nonce = 0;
uint256 public prize = 0;
event Roll(address indexed player, uint256 roll);
event Winner(address winner, uint256 amount);
constructor() payable {
resetPrize();
}
function resetPrize() private {
prize = ((address(this).balance * 10) / 100);
}
function rollTheDice() public payable {
require(msg.value >= 0.002 ether, "Failed to send enough value");
bytes32 prevHash = blockhash(block.number - 1);
bytes32 hash = keccak256(abi.encodePacked(prevHash, address(this), nonce));
uint256 roll = uint256(hash) % 16;
console.log('\t'," Dice Game Roll:",roll);
nonce++;
prize += ((msg.value * 40) / 100);
emit Roll(msg.sender, roll);
if (roll > 2 ) {
return;
}
uint256 amount = prize;
(bool sent, ) = msg.sender.call{value: amount}("");
require(sent, "Failed to send Ether");
resetPrize();
emit Winner(msg.sender, amount);
}
receive() external payable { }
}
Contract B
enter code here
contract RiggedRoll is Ownable {
DiceGame public diceGame;
constructor(address payable diceGameAddress) {
diceGame = DiceGame(diceGameAddress);
}
//Add withdraw function to transfer ether from the rigged contract to an address
//Add riggedRoll() function to predict the randomness in the DiceGame contract and only roll when it's going to be a winner
function riggedRoll(bytes32 riggedHash) public payable {
riggedHash = address(diceGame).blockhash(block.number-1); //I am aware this syntax is broken but I am not able to find a legitimate one to access the data from contract A.
}
//Add receive() function so contract can receive Eth
receive() external payable { }
}
A contract doesn't know when it was last called, unless you explicitly store this information.
Then you can get the block hash using the native blockhash() function (accepts the block number as a parameter).
contract Target {
uint256 public lastCalledAtBlockNumber;
// The value is stored only if you invoke the function using a (read-write) transaction.
// If you invoke the function using a (read-only) call, then it's not stored.
function foo() external {
lastCalledAtBlockNumber = block.number;
}
}
bytes32 blockHash = blockhash(block.number);

DeclarationError: Identifier not found or not unique

I'm trying to compile my sol file, but it's giving me this error. Why am I getting this error?
DeclarationError: Identifier not found or not unique. -->
project:/contracts/MemoTokenSale.sol:11:5: | 11 | MemoToken
public token; | ^^^^^^^^^
Compilation failed. See above. Truffle v5.4.23 (core: 5.4.23) Node
v16.13.0
The following is my code
// SPX-License-Identifier: MIT
pragma solidity ^0.8.0;
import './MemoToken.sol';
import "#chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
contract MemoTokenSale {
address payable public admin;
address payable private ethFunds = payable(0x15b22B37679eF92672dA117F4357e048319008AD); // Web3 Account
MemoToken public token;
uint256 public tokensSold;
int public tokenPriceUSD;
AggregatorV3Interface internal priceFeed;
uint256 public transactionCount;
event Sell(address _buyer, uint256 _amount);
struct Transaction {
address buyer;
uint256 amount;
}
mapping(uint256 => Transaction) public transaction;
constructor(MemoToken _token) {
priceFeed = AggregatorV3Interface(0x9326BFA02ADD2366b30bacB125260Af641031331); // ChainLink Contracts
tokenPriceUSD = 50;
token = _token;
admin = payable(msg.sender);
}
function getETHPrice() public view returns(int) {
(, int price, , , ) = priceFeed.latestRoundData();
return (price / 10^8);
}
function memoTokenPriceInETH() public view returns(int) {
int ethPrice = getETHPrice();
return tokenPriceUSD / ethPrice;
}
function buyToken(uint256 _amount) public payable {
int memoTokenPriceETH = memoTokenPriceInETH();
// Check that the buyer sends the enough ETH
require(int(msg.value) >= memoTokenPriceETH * int(_amount));
// Check that the sale contract provides the enough ETH to make this transaction.
require(token.balanceOf(address(this)) >= _amount);
// Make the transaction inside of the require
// transfer returns a boolean value.
require(token.transfer(msg.sender, _amount));
// Transfer the ETH of the buyer to us
ethFunds.transfer(msg.value);
// Increase the amount of tokens sold
tokensSold += _amount;
// Increase the amount of transactions
transaction[transactionCount] = Transaction(msg.sender, _amount);
transactionCount++;
// Emit the Sell event
emit Sell(msg.sender, _amount);
}
function endSale() public {
require(msg.sender == admin);
// Return the tokens that were left inside of the sale contract
uint256 amount = token.balanceOf(address(this));
require(token.transfer(admin, amount));
selfdestruct(payable(admin));
}
}

How to add method id in metamask

I have deployed smart contract using remix IDE, launched with Injected Web3 on Ropsten test network. I could call BuyTokens function within solidity IDE successfully, but when tried to buy tokens with metamask from other address transaction get reverted. I can see the difference between those operations on ropsten.etherscan explorer - the difference is in Input Data field.
Metamask transaction has value 0x and transaction via remix is:
Function: buyTokens() ***
MethodID: 0xd0febe4c
Code:
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;
contract Token {
// Track how many tokens are owned by each address.
mapping (address => uint256) public balanceOf;
// Modify this section
string public name = "DemoCoin";
string public symbol = "DC";
uint8 public decimals = 8;
uint256 public totalSupply = 1000000000 * (uint256(10) ** decimals);
address public owner;
//uint scaler = 10e18; // == 1 ETH in wei
//uint public coinPrice = 20; //initial price => 20 cents
event Transfer(address indexed from, address indexed to, uint256 value);
constructor() {
// Initially assign all tokens to the contract's creator.
owner = msg.sender;
balanceOf[msg.sender] = totalSupply;
emit Transfer(address(0), msg.sender, totalSupply);
}
// Might be executed automaticlly
// https://blog.chronologic.network/schedule-your-transaction-now-using-mycrypto-and-myetherwallet-17b48166b412
// function changeCoinPrice() public {
// uint newCoinPrice;
// require(msg.sender == address(0));
// coinPrice = newCoinPrice;
// }
function buyTokens() public payable {
// msg.value in wei so 1ETH = 10e18
// lets set 0.20 cents for 1 token
uint paidAmount;
require(balanceOf[msg.sender] >= paidAmount);
require(balanceOf[owner] >= value);
uint tokens;
tokens = value/10e14;
balanceOf[owner] -= tokens;
balanceOf[msg.sender] += tokens;
emit Transfer(owner, msg.sender, tokens);
}
function msgSenderBalancce() public view returns (uint) {
return balanceOf[msg.sender];
}
function withDrawEth() public view {
require(msg.sender == owner);
}
}
Why these methods are called diffrently? And how to add method id in metamask? Or am I missing something and this should be handled in other way?
MetaMask has a very basic UI. It only allows transfers of ETH and standardized tokens, but it doesn't show any buttons to call other contract functions. It also doesn't allow creating any custom buttons in their UI.
You'll need to set the data field of the transaction to 0xd0febe4c (which effectively executes the buyTokens() function).
But - they also don't allow specifying the data field value manually in the UI, so you'll need to preset it using the Ethereum provider API.
Your web app connects to the user's MetaMask acccount. It opens a MetaMask window and the user needs to manually confirm the connect.
The web app sends a request to MetaMask specifying the transaction with data field value.
The user confirms the transaction (which now includes the data field value 0xd0febe4c) in their MetaMask UI.

transact to Auction.placeBid errored: VM error: revert. revert The transaction has been reverted to the initial state

I signed up for a "introduction to Blockchain" course in my exchange semester in South Korea and I feel like it's not just an introduction because for half of the final grade we get we have to create our own simple dApp and I never really coded before.
So I copied and tried to understand this code for a simple auction app but it's not working because of this error:
transact to Auction.placeBid errored: VM error: revert. revert The transaction has been reverted to the initial state. Note: The called function should be payable if you send value and the value you send should be less than your current balance. Debug the transaction to get more information.
It took me a while to go through the code and I still don't understand all of it clearly so maybe I am missing something very simple since im a coding novice. Here's the code:
// We are using version 0.6.6 of Solidity
pragma solidity 0.6.6;
// We import OpenZeppelins SafeMath library to avoid bugs
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/math/SafeMath.sol";
contract AuctionBox{
Auction[] public auctions;
function createAuction (
string memory _title,
uint _startPrice,
string memory _description
) public {
// we set a new instance
Auction newAuction = new Auction(msg.sender, _title, _startPrice, _description);
// we add auction address to the auctions array
auctions.push(newAuction);
}
function returnAllAuctions() public view returns(Auction[] memory){
return auctions;
}
}
contract Auction {
using SafeMath for uint256;
address payable private owner;
string title;
uint startPrice;
string description;
enum State{Default, Running, Finalized}
State public auctionState;
uint public highestPrice;
address payable public highestBidder;
mapping(address => uint) public bids;
//constructor to creat an auction when the owner calls createAuction() in AuctionBox contract
constructor(
address payable _owner,
string memory _title,
uint _startPrice,
string memory _description
//_title is the title of the auction
// _startPrice is the start price of the auction
// _description is the description of the auction
) public {
// here we initialize auction
owner = _owner;
title = _title;
startPrice = _startPrice;
description = _description;
auctionState = State.Running;
}
modifier notOwner(){
require(msg.sender != owner);
_;
}
//the function to place a bid
function placeBid() public payable notOwner returns(bool) {
//to check the if the auctionState is running and if the bid is more than 1
require(auctionState == State.Running, "error: auctionState is not running");
require(msg.value >= 0, "error: bid value is lower than 0");
// to update the currentBid
uint currentBid = bids[msg.sender].add(msg.value);
// uint currentBid = bids[msg.sender] + msg.value;
require(currentBid > highestPrice);
// link the currentBid with msg.sender
bids[msg.sender] = currentBid;
// to update the highestPrice
highestPrice = currentBid;
highestBidder = msg.sender;
return true;
}
function finalizeAuction() public{
//to finalize the auction by owner or bidders
require(msg.sender == owner || bids[msg.sender] > 0);
address payable recipiant;
uint value;
// for the owner to get highestPrice
if(msg.sender == owner){
recipiant = owner;
value = highestPrice;
}
// for the highestBidder to not get the money back
else if (msg.sender == highestBidder){
recipiant = highestBidder;
value = 0;
}
// for the other bidders to get the money back
else {
recipiant = msg.sender;
value = bids[msg.sender];
}
// initialize the value
bids[msg.sender] = 0;
recipiant.transfer(value);
auctionState = State.Finalized;
}
//the function to show the auction content
function returnContent() public view returns(
string memory,
uint,
string memory,
State
) {
return (
title,
startPrice,
description,
auctionState
);
}
}
enter image description here
The "place bid" function always fails with the error message named in the title.
I tried to fix it with the help of the following threads but without success since I don't know how to apply it on my code:
https://medium.com/linum-labs/error-vm-exception-while-processing-transaction-revert-8cd856633793
Why am I getting this error ? "Gas estimation errored with the following message (see below). The transaction > execution will likely fail"
Gas estimation errored with the following message
"The transaction execution will likely fail. Do you want to force sending? VM Exception while processing transaction: out of gas"
Transaction revert in Remix
solidity

Solidity Syntax error - SENT

I'm learning Solidity from official documentation and stack on an exercise where I create simple coin:
pragma solidity ^0.4.20; // should actually be 0.4.21
contract Coin {
// The keyword "public" makes those variables
// readable from outside.
address public minter;
mapping (address => uint) public balances;
// Events allow light clients to react on
// changes efficiently.
event Sent(address from, address to, uint amount);
// This is the constructor whose code is
// run only when the contract is created.
function Coin() public {
minter = msg.sender;
}
function mint(address receiver, uint amount) public {
if (msg.sender != minter) return;
balances[receiver] += amount;
}
function send(address receiver, uint amount) public {
if (balances[msg.sender] < amount) return;
balances[msg.sender] -= amount;
balances[receiver] += amount;
emit Sent(msg.sender, receiver, amount);
}
}
When i try to compile i got a syntax error on the last line:
emit Sent(msg.sender, receiver, amount);
I tried to compile it in Remix and VS Code but got the same error message.
Can somebody help me pls?
The emit keyword was added in Solidity 0.4.21. Prior to that version, you emit events by using just the event name.
Sent(msg.sender, receiver, amount);
You can view the proposal here.