Solidity smart contract for lottery, but I can only give the prize for the first one. I want it to give it to all winners - solidity

Can't make it gives the prize for all winners, just the first one person that putted the right combination. I think there is a problem with findWinners function but I can't find it. If I make address A the good combination, then B with a not good one, and finally C with also a good one, it only gives the prize to A.
pragma solidity ^0.5.1;
contract Lottery {
Game[] ListGames;
// uint public nbGames = ListGames.length;
uint price = 100000;
uint[6] winnerGame;
// winnerGame = [1,2,3,4,5,6];
address payable[] ListWinners;
uint winnersPayed = 0;
uint expiredGames = 0;
struct Game {
address payable gamer;
uint[6] numbers;
uint date;
bool valid;
}
function setWinner(uint[6] memory _winnerGame) public {
winnerGame = _winnerGame;
}
function findWinners() public returns (address payable[] memory) {
uint size = ListGames.length;
bool win = true;
for (uint j = 0; j < size; j++) {
for (uint i=0; i<6 ; i++) {
if ((ListGames[j].numbers[i] != winnerGame[i]) || !ListGames[j].valid) {
win = false;
}
}
if (win) {
ListGames[j].valid = false;
expiredGames ++;
ListWinners.push(ListGames[j].gamer);
}
}
return ListWinners;
}
function payer() public returns (uint) {
uint nbWinners = ListWinners.length;
uint prize;
if (nbWinners - winnersPayed != 0) {
prize = address(this).balance / (nbWinners- winnersPayed);
for (uint i = 0; i < nbWinners; i++) {
if(ListWinners[i] != address(0)) {
ListWinners[i].transfer(prize);
delete ListWinners[i];
winnersPayed++;
require(ListWinners[i] == address(0));
}
}
}
return nbWinners;
}
modifier costs(uint amount) {
require(msg.value >= amount);
_;
}
function postGame(uint[6] memory _numbers) public payable costs(price) {
Game memory newGame = Game(msg.sender, _numbers, block. timestamp, true);
ListGames.push(newGame);
}
function numberValidGames() public view returns (uint) {
return ListGames.length - expiredGames;
}
function getWinnersList() public view returns (address payable [] memory) {
return ListWinners;
}
function getTime() public view returns (uint) {
return block.timestamp;
}
function getBalance() public view returns (uint) {
return address(this).balance;
}
}

Related

VM Exception while processing transaction: reverted with reason string 'message'

I don't understand what's wrong, why I am getting this error on function testing.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import "#openzeppelin/contracts/utils/Address.sol";
contract Voting {
address public owner;
uint public counter;
uint public minCandidates = 2;
uint public maxCandidates;
uint public immutable Comission;
struct Candidate {
uint balance;
bool isExistOnThisVoting;
}
struct _Voting {
bool started;
address Winner;
uint StartDate;
uint WinnerBalance;
uint Bank;
uint Period;
mapping(address => Candidate) Candidates;
}
mapping(uint => _Voting) private Votings;
modifier onlyOwner() {
require(msg.sender == owner, "Sorry, but you are not an owner!");
_;
}
constructor(uint _maxCandidates, uint _comission) {
owner = msg.sender;
Comission = _comission;
maxCandidates = _maxCandidates;
}
function addVoting(address[] calldata _candidates, uint _period) public onlyOwner {
require(minCandidates <= _candidates.length && _candidates.length < maxCandidates,
"The number of candidates must comply with the voting rules!"
);
Votings[counter].Period = _period;
for( uint i = 0; i < _candidates.length; i++) {
addCandidate(counter, _candidates[i]);
}
emit votingDraftCreated(counter);
counter++;
}
function editVotingPeriod(uint _id, uint _newPeriod) public onlyOwner {
require(Votings[_id].started = false, "The voting has already begun!");
Votings[_id].Period = _newPeriod;
}
function addCandidate(uint _id, address _candidate) public onlyOwner {
require(address(_candidate) != address(0), "This candidate with zero address!");
require(Address.isContract(_candidate) == false, "A contract can't be a candidate!");
require(Votings[_id].started, "The voting has already begun!");
Votings[_id].Candidates[_candidate].isExistOnThisVoting = true;
emit candidateInfo(_id, _candidate, true);
}
function deleteCandidate(address _candidate, uint _id) public onlyOwner {
require(Votings[_id].started, "The voting has already begun!");
Votings[_id].Candidates[_candidate].isExistOnThisVoting = false;
emit candidateInfo(_id, _candidate, false);
}
function startVoting(uint _id) public onlyOwner {
Votings[_id].started = true;
Votings[_id].StartDate = block.timestamp;
emit votingStarted(_id, block.timestamp);
}
function takePartInVoting(uint _id, address _candidate) public payable {
require(Address.isContract(msg.sender) == false, "A contract can't vote!");
require(Votings[_id].started, "The voting doesn't start!");
require(Votings[_id].StartDate + Votings[_id].Period > block.timestamp, "The voting has ended!");
require(checkCandidate(_id, _candidate), "This candidates does not exist in this voting!");
Votings[_id].Candidates[_candidate].balance += msg.value;
Votings[_id].Bank += msg.value;
if (Votings[_id].Candidates[_candidate].balance > Votings[_id].WinnerBalance) {
Votings[_id].WinnerBalance = Votings[_id].Candidates[_candidate].balance;
Votings[_id].Winner = _candidate;
}
}
function withDrawPrize(uint _id) public {
require(Votings[_id].started, "The voting doesn't start!");
require(Votings[_id].StartDate + Votings[_id].Period < block.timestamp, "The voting is not ended yet!");
require(msg.sender == Votings[_id].Winner, "You are not a winner!");
require(Votings[_id].Bank > 0, "You have already receive your prize!");
uint amount = Votings[_id].Bank;
uint ownerComission = (Comission * amount) / 100;
uint clearAmount = amount - ownerComission;
Votings[_id].Bank = 0;
payable(owner).transfer(ownerComission);
payable(msg.sender).transfer(clearAmount);
}
function checkCandidate(uint _id, address _candidate) public view returns(bool) {
return(Votings[_id].Candidates[_candidate].isExistOnThisVoting);
}
function getVotingInfo(uint256 _id) public view returns (
bool,
uint256,
uint256,
uint256,
uint256,
address
) {
return(
Votings[_id].started,
Votings[_id].StartDate,
Votings[_id].WinnerBalance,
Votings[_id].Bank,
Votings[_id].Period,
Votings[_id].Winner);
}
function setMaxCandidates(uint _maxCandidates) public onlyOwner {
require(minCandidates <= _maxCandidates, "Minimum number of candidates is 2");
maxCandidates = _maxCandidates;
}
event candidateInfo(uint indexed id, address indexed candidate, bool existOnThisVoting);
event votingDraftCreated(uint indexed id);
event votingStarted(uint indexed id, uint startDate);
}
Here is the contract and the test for it:
const { time, loadFixture } = require("#nomicfoundation/hardhat-network-helpers");
const { ethers } = require("hardhat");
const { expect } = require("chai");
describe("Voting", function () {
async function deploy() {
const [owner, user] = await ethers.getSigners();
const Voting = await ethers.getContractFactory("Voting");
const myVoting = await Voting.deploy(5, 10);
return { myVoting, owner, user };
}
it("An owner can change voting's period", async function () {
const { myVoting, owner } = await loadFixture(deploy);
await myVoting.connect(owner).editVotingPeriod(0, 200);
const _votingInfo = await myVoting.getVotingInfo(0);
expect(_votingInfo[2]).to.equal(200);
});
it("Owner can create another voting", async function () {
const { myVoting, owner, user } = await loadFixture(deploy);
const counter_before = await myVoting.counter();
let candidates = new Array();
for (i = 1; i < 4; i++) candidates.push(owner.address);
await myVoting.connect(owner).addVoting(candidates, 100);
const is_candidate = await myVoting.checkCandidate(counter_before, user.address);
expect(is_candidate).to.equal(false);
});
And only two tests are failing with message -> Error: VM Exception while processing transaction: reverted with reason string 'The voting has already begun!'
Could somebody help me to understand why did I get this error?
I don't understand why I got this error.
I found a bug in the solidity code. You're using = instead of == in this line:
require(Votings[_id].started = false, "The voting has already begun!");
I'm not sure this alone will fix your problem, but try again!

TypeError: Explicit type conversion not allowed from "uint256" to "address"

i make simple code, but have error "TypeError: Explicit type conversion not allowed from "uint256" to "address"." Can you help me? I even asked the gpt bot about this error, but it confused me even more)))
in the beginning there was a simple idea - 10k nft, 30 of them immediately after the deposit, the minimum price is indicated and everyone can buy without restriction
`pragma solidity ^0.8.4;
import "#openzeppelin/contracts/token/ERC721/ERC721.sol";
contract Sptzrawef is ERC721 {
// Define the token name, symbol, and maximum supply
uint256 public totalSupply = 10000;
string public tokenURI;
// Define the owner of the contract
address public owner;
// Define the minimum price of the token
uint256 public minPrice;
// Define the mapping for the token ownership
mapping(address => mapping(uint256 => bool)) public tokenOwnership;
// The constructor function
constructor() ERC721("Sptzrawef", "SP") {
tokenURI = "https://nftstorage.link/ipfs/ba.................q3oq/";
owner = msg.sender;
minPrice = 0.025 ether;
totalSupply = 10000;
// Mint 30 tokens immediately upon deployment
for (uint256 i = 1; i <= 30; i++) {
tokenOwnership[msg.sender][i] = true;
}
}
// Function to mint new tokens
function mint(address _to, uint256 _tokenId) public {
require(msg.sender == owner);
require(_tokenId <= totalSupply);
require(tokenOwnership[_to][_tokenId] == false);
tokenOwnership[_to][_tokenId] = true;
totalSupply++;
}
// Function to buy the token
function buy(uint256 _tokenId) public payable {
require(msg.value >= minPrice);
require(tokenOwnership[msg.sender][_tokenId] == false);
require(_tokenId <= totalSupply);
tokenOwnership[msg.sender][_tokenId] = true;
}
function balanceOf() public view returns (uint256) {
return totalSupply;
}
function tokenOfOwnerByIndex(address _owner, uint256 _index) public view returns (uint256) {
uint256 count = 0;
for (uint256 i = 1; i <= totalSupply; i++) {
if (tokenOwnership[_owner][i]) {
if (count == _index) {
return i;
}
count++;
}
}
return 0;
}
function ownerOf(uint256 _tokenId) public view override returns (address) {
require(_tokenId <= totalSupply);
for (uint256 i = 0; i < totalSupply; i++) {
address wallet = address(i); - error at this line
if (tokenOwnership[wallet][_tokenId]) {
return wallet;
}
}
return address(0);
}
}`
I think you are using ownerOf function in the wrong way.
try to create a new "getWalletAddress" function, for example, and use it in this way:
function getWalletAddress(uint256 _tokenId) public view returns (address) {
require(_tokenId <= totalSupply);
for (uint256 i = 0; i < totalSupply; i++) {
address wallet = ownerOf(i);
if (tokenOwnership[wallet][_tokenId]) {
return wallet;
}
}
return address(0);
}
}
Or if you want to override the "ownerOf" function then you should go for this code:
function ownerOf(uint256 _tokenId) public view overrides returns (address) {
require(_tokenId <= totalSupply);
for (uint256 i = 0; i < totalSupply; i++) {
address wallet = _ownerOf(i);
if (tokenOwnership[wallet][_tokenId]) {
return wallet;
}
}
return address(0);
}
}
I hope this help resolve your issue
address is 20bytes and uint256 is 32bytes.
Therefore, you need to use uint160 for the type of i to convert it to address.
Or please convert i into uint160 before converting it to address
address wallet = address(uint160(i));

Gas Estimation Failed: Internal JSON-RPC Error (Code 3)

I created a pool contract for stacking invest. But when I deployed on testnet with Remix IDE and I trying to execute function invest, I got this Internal JSON-RPC Error. Guys please help me to find where is the problem in the entire code. Here is the full code:
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;
import "#openzeppelin/contracts/utils/math/SafeMath.sol";
import "#openzeppelin/contracts/utils/Address.sol";
import "#openzeppelin/contracts/token/ERC20/IERC20.sol";
import "#openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "#openzeppelin/contracts/utils/Context.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
contract StarzBit is Ownable {
using SafeERC20 for IERC20;
struct Deposit {
uint index;
uint checkpoint;
}
struct User {
address referer;
address account;
Deposit[] deposits;
uint[] partners;
uint totalDeposit;
uint totalWithdrawn;
uint totalBonus;
uint directBonus;
uint teamBonus;
uint checkpoint;
}
struct Level {
uint level;
uint lvl0; // partner
uint lvl1;
uint lvl2;
uint lvl3;
uint lvl4;
uint team; // total Team count
}
IERC20 public token;
uint public price;
uint public maxUnits = 2;
uint public minUnits = 1;
uint public totalDeposit;
uint public depositCount;
uint public totalBonus;
uint public totalWithdrawn;
uint public totalCommission;
uint public totalUsers;
uint public commissionFeeRate = 100;
uint public levelStep = 3;
uint[] public referRate = [8, 5, 3, 2];
address[] public team;
uint public teamRate = 20;
uint public marketingFee = 50;
address public marketingWallet = 0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2;
address public firstWallet = 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4;
bool enabled = false;
mapping(address => uint) public userids;
mapping(uint => User) public users;
mapping(uint => Level) public levels;
mapping(uint => address) public depositIndexToAccount;
event UserMsg(uint userid, string msg, uint value);
event Commission(uint value);
constructor(IERC20 _token, uint _price) {
token = _token;
price = _price;
}
receive() external payable {}
function invest(address referer, uint units) external {
require(enabled, "Pool Not Enabled");
require(units >= minUnits, "Less than Min Units");
require(units <= maxUnits, "Over than Max Units");
uint userid = userids[msg.sender];
if (userid == 0) {
totalUsers += 1;
userid = totalUsers;
userids[msg.sender] = userid;
emit UserMsg(userid, "Joined", 0);
}
User storage user = users[userid];
if (user.account == address(0)) {
user.account = msg.sender;
user.checkpoint = block.timestamp;
}
if (user.referer == address(0) && referer != address(0)) {
if (users[userids[referer]].totalDeposit > 0 && referer != msg.sender && user.totalDeposit == 0) {
user.referer = referer;
users[userids[referer]].partners.push(userid);
processLevelUpdate(referer, msg.sender);
address parent = referer;
for (uint i = 0; i < 5; i++) {
if (parent == address(0)) break;
levels[userids[parent]].team += 1;
parent = users[userids[parent]].referer;
}
}
}
// uint value;
// payForCommission(referer, value);
processDeposit(units);
payReferral(referer, units);
}
function payForCommission(address referer, uint value) private returns (uint){
address upline = referer;
uint totalRefOut;
for (uint i = 0; i < referRate.length; i++) {
uint uplineId = userids[upline];
if (uplineId == 0) break;
if (upline != address(0) && levels[uplineId].level > i) {
uint bonus = value * referRate[i] / 1000;
totalRefOut = totalRefOut + bonus;
token.safeTransfer(upline, bonus);
// emit PayBonus(upline, bonus);
emit UserMsg(uplineId, "RefBonus", bonus);
users[uplineId].totalBonus += bonus;
if (i == 0) {
users[uplineId].directBonus += bonus;
}
upline = users[uplineId].referer;
} else break;
}
for (uint i = 0; i < team.length; i++) {
uint bonus = value * teamRate / 1000 / team.length;
totalRefOut += bonus;
token.safeTransfer(team[i], bonus / team.length);
// emit PayBonus(team[i], bonus);
emit UserMsg(userids[team[i]], "TeamBonus", bonus);
users[userids[team[i]]].totalBonus += bonus;
users[userids[team[i]]].teamBonus += bonus;
}
totalBonus += totalRefOut;
uint marketingOut = value * marketingFee / 1000;
token.safeTransfer(marketingWallet, marketingOut);
uint commi = totalRefOut + marketingOut;
emit Commission(commi);
return commi;
}
function getCommissionRate() public view returns(uint) {
return commissionFeeRate;
}
function payReferral(address referer, uint units) private {
// pay to referral
uint value = price * units;
uint commission = value * commissionFeeRate / 1000;
uint totalRefOut;
address upline = referer;
for (uint i = 0; i < referRate.length; i++) {
uint uplineId = userids[upline];
if (uplineId == 0) break;
if (upline != address(0) && levels[uplineId].level > i) {
if (users[uplineId].totalDeposit > users[uplineId].totalWithdrawn) {
uint bonus = value * referRate[i] / 1000;
totalRefOut = totalRefOut + bonus;
token.safeTransfer(upline, bonus);
// emit PayBonus(upline, bonus);
emit UserMsg(uplineId, "RefBonus", bonus);
users[uplineId].totalBonus += bonus;
if (i == 0) {
users[uplineId].directBonus += bonus;
}
}
upline = users[uplineId].referer;
} else break;
}
for (uint i = 0; i < team.length; i++) {
uint bonus = value * teamRate / 1000 / team.length;
totalRefOut += bonus;
token.safeTransfer(team[i], bonus / team.length);
// emit PayBonus(team[i], bonus);
emit UserMsg(userids[team[i]], "TeamBonus", bonus);
users[userids[team[i]]].totalBonus += bonus;
users[userids[team[i]]].teamBonus += bonus;
}
uint commi = commission - totalRefOut;
token.safeTransfer(marketingWallet, commi);
emit Commission(commi);
totalBonus += totalRefOut;
totalCommission += commission;
}
function processLevelUpdate(address referer, address from) private {
if (referer == address(0)) return;
uint refererid = userids[referer];
if (refererid == 0) return;
uint fromid = userids[from];
User storage user = users[refererid];
Level storage level = levels[refererid];
if (levels[fromid].level == 0) {
level.lvl0++;
if (level.lvl0 >= levelStep && level.level < 1) {
level.level = 1;
emit UserMsg(refererid, "LevelUp", 1);
processLevelUpdate(user.referer, referer);
}
} else if (levels[fromid].level == 1) {
level.lvl1++;
if (level.lvl1 >= levelStep && level.level < 2) {
level.level = 2;
emit UserMsg(userids[referer], "LevelUp", 2);
processLevelUpdate(user.referer, referer);
}
} else if (levels[fromid].level == 2) {
level.lvl2++;
if (level.lvl2 >= levelStep && level.level < 3) {
level.level = 3;
emit UserMsg(userids[referer], "LevelUp", 3);
processLevelUpdate(user.referer, referer);
}
} else if (levels[fromid].level == 3) {
level.lvl3++;
if (level.lvl3 >= levelStep && level.level < 4) {
level.level = 4;
emit UserMsg(userids[referer], "LevelUp", 4);
processLevelUpdate(user.referer, referer);
}
} else if (levels[fromid].level == 4) {
level.lvl4++;
if (level.lvl4 >= levelStep && level.level < 5) {
level.level = 5;
emit UserMsg(userids[referer], "LevelUp", 5);
processLevelUpdate(user.referer, referer);
}
}
}
function processDeposit(uint units) private returns (uint value) {
uint userid = userids[msg.sender];
User storage user = users[userid];
require(userAllocated(msg.sender) >= user.totalDeposit, "Less Allocated");
value = units * price;
token.safeTransferFrom(msg.sender, address(this), value);
totalDeposit += value;
emit UserMsg(userid, "Deposit", value);
for (uint i = 0; i < units; i++) {
Deposit memory deposit = Deposit(depositCount + i, block.timestamp);
user.deposits.push(deposit);
depositIndexToAccount[depositCount + i] = msg.sender;
// push deposit nature index
}
depositCount += units;
user.totalDeposit += value;
}
function claim() external {
uint userid = userids[msg.sender];
User storage user = users[userid];
uint allocated = userAllocated(msg.sender);
require(allocated > user.totalWithdrawn, "No more allocated");
uint topay = allocated - user.totalWithdrawn;
user.totalWithdrawn += topay;
totalWithdrawn += topay;
emit UserMsg(userid, "Claim", topay);
}
function userAllocated(address account) public view returns (uint) {
if (depositCount < 1) return 0;
uint userid = userids[account];
User storage user = users[userid];
uint weight;
for (uint i = 0; i < user.deposits.length; i += 1) {
weight += (depositCount - user.deposits[i].index);
}
return totalDeposit * weight / totalWeight();
}
function userPercent(address account) public view returns (uint) {
return userWeight(account) * depositCount * 100 / totalWeight();
}
function userWeight(address account) public view returns (uint) {
uint userid = userids[account];
User storage user = users[userid];
uint weight;
for (uint i = 0; i < user.deposits.length; i += 1) {
weight += (depositCount - user.deposits[i].index);
}
return weight;
}
function totalWeight() public view returns (uint) {
return depositCount * (depositCount + 1) / 2;
}
function userInfoById(uint id) public view returns(uint, uint, User memory, Level memory) {
User storage user = users[id];
Level storage level = levels[id];
return (id, userids[user.referer], user, level);
}
function userInfoByAddress(address account) public view returns(uint, uint, User memory, Level memory) {
uint userid = userids[account];
return userInfoById(userid);
}
function partnerIdsById(uint id) public view returns (uint[] memory){
User storage user = users[id];
return user.partners;
}
function withdraw(uint amount) external onlyOwner {
if (address(this).balance > 0) {
payable(msg.sender).transfer(address(this).balance);
}
if (token.balanceOf(address(this)) > 0) {
token.safeTransfer(msg.sender, amount);
}
}
function setCommissionFeeRate(uint rate) external onlyOwner {
commissionFeeRate = rate;
}
function setReferRate(uint[] memory rates) external onlyOwner {
referRate = rates;
}
function setLevelStep(uint step) external onlyOwner {
levelStep = step;
}
function levelteam() public view returns (address [] memory) {
return team;
}
function setMarketingWallet(address wallet) external onlyOwner {
marketingWallet = wallet;
}
function setEnabled(bool action) external onlyOwner {
enabled = action;
}
function setToken(IERC20 _token) external onlyOwner {
token = _token;
}
function setPrice(uint _price) external onlyOwner {
price = _price;
}
function setMaxUnits(uint units) external onlyOwner {
maxUnits = units;
}
function setMinUnits(uint units) external onlyOwner {
minUnits = units;
}
function setMarketingFee(uint fee) external onlyOwner {
marketingFee = fee;
}
function siteInfo() external view returns (uint, uint, uint, uint, uint, uint, uint, uint, bool) {
return (price, minUnits, maxUnits, totalDeposit, depositCount, totalBonus, totalWithdrawn, totalUsers, enabled);
}
}
The error show like this:
click to see image

Why is getResults giving me "0"

I've copied a smart contract from other project and trying to do my own from there, I understand solidity but I'm not good enough yet to make a contract from scratch.
So, in this contract I have 6 plans, with values are the amount of days and the daily % of profit. This daily % of profit increases 0.5% per day in all 6 plans.
First plan in the index (0) has 14 days and 8% base daily profit.
When I use the getResults function it retrieves the updated daily profit and makes the calculation to let the user know how much profit will get if investing X amount of tokens, but somehow when I enter a deposit:10 in plan:0 gives me a profit of 0, if I enter deposit:100, plan:0 I get the correct math, it's driving me crazy.
Here is the smart contract (had to put it into a snippet because it breaks the bb code in stackoverflow page):
pragma solidity >=0.4.22 <0.9.0;
contract testing {
using SafeMath for uint256;
uint256 constant public INVEST_MIN_AMOUNT = 10 ether;
uint256[] public REFERRAL_PERCENTS = [60, 40, 20];
uint256 constant public PROJECT_FEE = 100;
uint256 constant public PERCENT_STEP = 5;
uint256 constant public WITHDRAW_FEE = 1000; //In base point
uint256 constant public PERCENTS_DIVIDER = 1000;
uint256 constant public TIME_STEP = 1 days;
uint256 public totalStaked;
uint256 public totalRefBonus;
struct Plan {
uint256 time;
uint256 percent;
}
Plan[] internal plans;
struct Deposit {
uint8 plan;
uint256 percent;
uint256 amount;
uint256 profit;
uint256 start;
uint256 finish;
}
struct User {
Deposit[] deposits;
uint256 checkpoint;
address referrer;
uint256[3] levels;
uint256 bonus;
uint256 totalBonus;
}
mapping (address => User) internal users;
uint256 public startUNIX;
address payable public commissionWallet;
event Newbie(address user);
event NewDeposit(address indexed user, uint8 plan, uint256 percent, uint256 amount, uint256 profit, uint256 start, uint256 finish);
event Withdrawn(address indexed user, uint256 amount);
event RefBonus(address indexed referrer, address indexed referral, uint256 indexed level, uint256 amount);
event FeePayed(address indexed user, uint256 totalAmount);
constructor(address payable wallet, uint256 startDate) public {
require(!isContract(wallet));
require(startDate > 0);
commissionWallet = wallet;
startUNIX = startDate;
plans.push(Plan(14, 80));
plans.push(Plan(21, 65));
plans.push(Plan(28, 50));
plans.push(Plan(14, 80));
plans.push(Plan(21, 65));
plans.push(Plan(28, 50));
}
function invest(address referrer, uint8 plan) public payable {
require(msg.value >= INVEST_MIN_AMOUNT);
require(plan < 6, "Invalid plan");
uint256 fee = msg.value.mul(PROJECT_FEE).div(PERCENTS_DIVIDER);
commissionWallet.transfer(fee);
emit FeePayed(msg.sender, fee);
User storage user = users[msg.sender];
if (user.referrer == address(0)) {
if (users[referrer].deposits.length > 0 && referrer != msg.sender) {
user.referrer = referrer;
}
address upline = user.referrer;
for (uint256 i = 0; i < 3; i++) {
if (upline != address(0)) {
users[upline].levels[i] = users[upline].levels[i].add(1);
upline = users[upline].referrer;
} else break;
}
}
if (user.referrer != address(0)) {
address upline = user.referrer;
for (uint256 i = 0; i < 3; i++) {
if (upline != address(0)) {
uint256 amount = msg.value.mul(REFERRAL_PERCENTS[i]).div(PERCENTS_DIVIDER);
users[upline].bonus = users[upline].bonus.add(amount);
users[upline].totalBonus = users[upline].totalBonus.add(amount);
emit RefBonus(upline, msg.sender, i, amount);
upline = users[upline].referrer;
} else break;
}
}
if (user.deposits.length == 0) {
user.checkpoint = block.timestamp;
emit Newbie(msg.sender);
}
(uint256 percent, uint256 profit, uint256 finish) = getResult(plan, msg.value);
user.deposits.push(Deposit(plan, percent, msg.value, profit, block.timestamp, finish));
totalStaked = totalStaked.add(msg.value);
emit NewDeposit(msg.sender, plan, percent, msg.value, profit, block.timestamp, finish);
}
function withdraw() public {
User storage user = users[msg.sender];
uint256 totalAmount = getUserDividends(msg.sender);
uint256 fees = totalAmount.mul(WITHDRAW_FEE).div(10000);
totalAmount = totalAmount.sub(fees);
uint256 referralBonus = getUserReferralBonus(msg.sender);
if (referralBonus > 0) {
user.bonus = 0;
totalAmount = totalAmount.add(referralBonus);
}
require(totalAmount > 0, "User has no dividends");
uint256 contractBalance = address(this).balance;
if (contractBalance < totalAmount) {
totalAmount = contractBalance;
}
user.checkpoint = block.timestamp;
msg.sender.transfer(totalAmount);
emit Withdrawn(msg.sender, totalAmount);
}
function getContractBalance() public view returns (uint256) {
return address(this).balance;
}
function getPlanInfo(uint8 plan) public view returns(uint256 time, uint256 percent) {
time = plans[plan].time;
percent = plans[plan].percent;
}
function getPercent(uint8 plan) public view returns (uint256) {
if (block.timestamp > startUNIX) {
return plans[plan].percent.add(PERCENT_STEP.mul(block.timestamp.sub(startUNIX)).div(TIME_STEP));
} else {
return plans[plan].percent;
}
}
function getResult(uint8 plan, uint256 deposit) public view returns (uint256 percent, uint256 profit, uint256 finish) {
percent = getPercent(plan);
if (plan < 3) {
profit = deposit.mul(percent).div(PERCENTS_DIVIDER).mul(plans[plan].time);
} else if (plan < 6) {
for (uint256 i = 0; i < plans[plan].time; i++) {
profit = profit.add((deposit.add(profit)).mul(percent).div(PERCENTS_DIVIDER));
}
}
finish = block.timestamp.add(plans[plan].time.mul(TIME_STEP));
}
function getUserDividends(address userAddress) public view returns (uint256) {
User storage user = users[userAddress];
uint256 totalAmount;
for (uint256 i = 0; i < user.deposits.length; i++) {
if (user.checkpoint < user.deposits[i].finish) {
if (user.deposits[i].plan < 3) {
uint256 share = user.deposits[i].amount.mul(user.deposits[i].percent).div(PERCENTS_DIVIDER);
uint256 from = user.deposits[i].start > user.checkpoint ? user.deposits[i].start : user.checkpoint;
uint256 to = user.deposits[i].finish < block.timestamp ? user.deposits[i].finish : block.timestamp;
if (from < to) {
totalAmount = totalAmount.add(share.mul(to.sub(from)).div(TIME_STEP));
}
} else if (block.timestamp > user.deposits[i].finish) {
totalAmount = totalAmount.add(user.deposits[i].profit);
}
}
}
return totalAmount;
}
function getUserCheckpoint(address userAddress) public view returns(uint256) {
return users[userAddress].checkpoint;
}
function getUserReferrer(address userAddress) public view returns(address) {
return users[userAddress].referrer;
}
function getUserDownlineCount(address userAddress) public view returns(uint256, uint256, uint256) {
return (users[userAddress].levels[0], users[userAddress].levels[1], users[userAddress].levels[2]);
}
function getUserReferralBonus(address userAddress) public view returns(uint256) {
return users[userAddress].bonus;
}
function getUserReferralTotalBonus(address userAddress) public view returns(uint256) {
return users[userAddress].totalBonus;
}
function getUserReferralWithdrawn(address userAddress) public view returns(uint256) {
return users[userAddress].totalBonus.sub(users[userAddress].bonus);
}
function getUserAvailable(address userAddress) public view returns(uint256) {
return getUserReferralBonus(userAddress).add(getUserDividends(userAddress));
}
function getUserAmountOfDeposits(address userAddress) public view returns(uint256) {
return users[userAddress].deposits.length;
}
function getUserTotalDeposits(address userAddress) public view returns(uint256 amount) {
for (uint256 i = 0; i < users[userAddress].deposits.length; i++) {
amount = amount.add(users[userAddress].deposits[i].amount);
}
}
function getUserDepositInfo(address userAddress, uint256 index) public view returns(uint8 plan, uint256 percent, uint256 amount, uint256 profit, uint256 start, uint256 finish) {
User storage user = users[userAddress];
plan = user.deposits[index].plan;
percent = user.deposits[index].percent;
amount = user.deposits[index].amount;
profit = user.deposits[index].profit;
start = user.deposits[index].start;
finish = user.deposits[index].finish;
}
function isContract(address addr) internal view returns (bool) {
uint size;
assembly { size := extcodesize(addr) }
return size > 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;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a, "SafeMath: subtraction overflow");
uint256 c = a - b;
return c;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: division by zero");
uint256 c = a / b;
return c;
}
}
I think I found the issue. Since we are only handling integers there are no double type of variables, in the division it was rounding to 0, then when multiplied still being 0.
I've changed the div to be last part of the operation.
Replace this:
profit = deposit.mul(percent).div(PERCENTS_DIVIDER).mul(plans[plan].time);
to this:
profit = deposit.mul(percent).mul(plans[plan].time).div(PERCENTS_DIVIDER);

Try to return an array in a for loop

I am very new to Solidity, so sorry for the silly question. I am trying to add an element of a struct and then return it, here is my code:
struct Flat {
uint256 priceInWei;
address currentOccupant;
bool flatIsAvailable;
}
Flat[8] public flatDB;
modifier landlordOnly() {
require(msg.sender == landlordAddress);
_;
}
constructor() public {
landlordAddress = msg.sender;
for (uint i=0; i<8; i++) {
flatDB[i].flatIsAvailable = true;
if (i % 2 == 0) {
flatDB[i].priceInWei = 0.1 ether;
} else {
flatDB[i].priceInWei = 0.2 ether;
}
}
}
uint256[] array;
function getFlatDB() payable public returns (uint256) {
for (uint i=0; i<8; i++) {
array.push(flatDB[i].priceInWei);
}
return array;
}
But when I try to compile I have an error at line 41:
TypeError: Return argument type uint256[] storage ref is not implicitly convertible to expected type (type of first return variable) uint256. return array; ^---^
Can someone explain me what's wrong? Thanks!
Seems like the return type you have (uint256) doesn't correspond to the type you're actually trying to return (uint256[]). Try rewriting your getFlatDB function in the following way:
function getFlatDB() payable public returns (uint256[]) {
uint256[] memory array = new uint256[](8);
for (uint i=0; i<8; i++) {
array[i] = flatDB[i].priceInWei;
}
return array;
}
Note how we declare the temporary fixed size return array inside the function with memory keyword.