For/If Loop has no errors but does not push the value to the array - ethereum

I am trying to create a whitelist. I've used a for and if loop to check if the msg.sender already exists in the array. When the whitelist() function is run, no errors are returned, but when I run check(), it tells me the address doesn't exist in the array, same thing with directing fetching the array.
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract SelfWhitelist {
address[] public addressWhitelist;
function whitelist() public returns(string memory) {
for(uint i = 0; i < addressWhitelist.length; i++) {
if(addressWhitelist[i] != msg.sender) {
addressWhitelist.push(msg.sender);
return "Whitelisted!";
}
}
return "Already whitelisted!";
}
function check() public view returns (bool){
for(uint i = 0; i < addressWhitelist.length; i++){
if(addressWhitelist[i] == msg.sender)
return true;
}
return false;
}
}
I added this block of code to check for duplicate entries in the array.
for(uint i = 0; i < addressWhitelist.length; i++) {
if(addressWhitelist[i] != msg.sender) {
addressWhitelist.push(msg.sender);
return "Whitelisted!";
}
Expected for no errors and my address being pushed to the array.
The code ran without errors, but nothing was added to the array.

I would use mapping type to hold the whitelisted addresses, then you don't have to loop over the array
contract SelfWhitelist {
mapping(address => bool) public addressWhitelist;
function whitelist() public returns(string memory) {
if (check()) {
return "Already whitelisted!";
}
addressWhitelist[msg.sender] = true;
return "Whitelisted!";
}
function check() public view returns (bool) {
return addressWhitelist[msg.sender];
}
}
And in your code, seems you have logical issues:
for(uint i = 0; i < addressWhitelist.length; i++) {
if(addressWhitelist[i] != msg.sender) {
addressWhitelist.push(msg.sender);
return "Whitelisted!";
}
}
if the array is empty, the loop never executes, so nothing will be added
if the first item is not msg.sender, msg.sender will be whitelisted, even though it might be already whitelisted.

Related

ParserError: Expected '(' but got identifier function availableToWithdraw(address walletAddress) public returns(bool)

Im following a youtube tutorial on smart contracts as i am still very new to solidity however when I compile I am getting this error.
ParserError: Expected '(' but got identifier
--> contracts/CryptoKids.sol:57:14:
|
57 | function availableToWithdraw(address walletAddress) public returns(bool)
| ^^^^^^^^^^^^^^^^^^^
// SPDX-License-Identifier: Unlicensed
pragma solidity ^0.8.7;
contract CryptoKids
{
//Define Dad
address owner;
constructor(){
owner = msg.sender;
}
//Define Kid
struct Kid{
address payable walletAddress;
string firstName;
string LastName;
uint releaseTime;
uint amount;
bool canWithdraw;
}
Kid[] public kids;
//add kid to contract
function addKids(address payable walletAddress,string memory firstName,string memory LastName,uint releaseTime,uint amount,bool canWithdraw) public{
kids.push(Kid(walletAddress,firstName,LastName,releaseTime,amount,canWithdraw));
}
//deposit funds to contract, specifically to kids contract
function deposit(address walletAddress) payable public {
addToKidsBalance(walletAddress);
}
function balanceOf() public view returns(uint){
return address(this).balance;
}
function addToKidsBalance(address walletAddress) private{
for (uint i = 0; i < kids.length; i++){
if(kids[i].walletAddress == walletAddress){
kids[i].amount += msg.value;
}
}
}
function getIndex(address walletAddress) view private returns(uint){
for (uint i = 0; i < kids.length; i++){
if(kids[i].walletAddress == walletAddress){{
return i;
}
}
return 999;
}
//kid checks if can withdraw
function availableToWithdraw(address walletAddress) public returns(bool)
{
uint i = getIndex(walletAddress);
if (block.timestamp > kids[1].releaseTime)
{
kids[i].canWithdraw = true;
return true;
}
else
{
return false;
}
}
//if can withdraw money
function withdraw(address payable walletAddress) payable public{
uint i = getIndex(walletAddress);
kids[i].walletAddress.transfer(kids[i].amount);
}
}
Im not sure what the issue is as ive checked my codes with against the video that im following and cant find anything wrong
Video Link: https://www.youtube.com/watch?v=s9MVkHKV2Vw
In your getIndex() function remove a curly bracket in the end of the following if condition:
function getIndex(address walletAddress) view private returns(uint){
for (uint i = 0; i < kids.length; i++){
if(kids[i].walletAddress == walletAddress){{ // <- This is the issue
return i;
}
}
return 999;
}
Replace it with:
function getIndex(address walletAddress) view private returns(uint){
for (uint i = 0; i < kids.length; i++){
if(kids[i].walletAddress == walletAddress) {
return i;
}
}
return 999;
}

Expected ';' but got 'constructor'

Hi everyone, i wrote some solidity code, but unfortunately got some error, what's the matter?
I was using HardHat to compile my code and got next error:
Error looks like this:
ParserError: Expected ';' but got 'constructor'
--> contracts/Tree.sol:14:5
Code looks like this:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Tree {
bytes32[] hashes;
string[4] transactions = [
"first transaction",
"second transaction",
"third transaction",
"fourth transaction"
];
constructor() {
for (uint i = 0; i < transactions.length; i++) {
hashes.push(makeHash(transactions[i]));
}
uint count = transactions.length;
uint offset = 0;
while (count > 0) {
for (uint i = 0; i < count - 1; i += 2) {
hashes.push(
keccak256(
abi.encodePacked(
hashes[offset + 1],
hashes[offset + i + 1]
)
)
);
}
offset += count;
count = count / 2;
}
}
function verify(
string memory transaction,
uint index,
bytes32 root,
bytes32[] memory proof
) public pure returns (bool) {
bytes32 hash = makeHash(transaction);
for (uint i = 0; i < proof.length; i++) {
bytes32 element = proof[i];
if (index % 2 == 0) {
hash = keccak256(abi.encodePacked(hash, element));
} else {
hash = keccak256(abi.encodePacked(element, hash));
}
index = index / 2;
}
return root == hash;
}
function encode(string memory input) public pure returns (bytes memory) {
return abi.encodePacked(input);
}
function makeHash(string memory input) public pure returns (bytes32) {
return keccak256(encode(input));
}
}
I'm not able to reproduce your issue. Above provided code is completely Okay and compiles fine.
However, it issue might be that you have missed a semicolon ; at the end of array string transactions while compiling however, replaced here while uploading the code.

Solidity CRUD trying to call All data return instead of one by one using ID

I have created a solidity that record data CRUD like where I can create read update delete but I want to create a readAll function wondering how can I write in solidity since I write like below it does not work. For calling with id it return the correct but not readAll. Looking forward for your help <3
example
function readAllTask() public view returns (uint, uint256, uint256) {
return (tasks.id, tasks.stackAddress, tasks.nftId); <============= return everything
}
pragma solidity ^0.8.6;
contract RecordData {
struct Task {
uint id;
uint256 stackAddress;
uint256 nftId;
}
Task[] tasks;
uint nextId; // default value 0, add public to see the value
function createTask(uint256 _stackAddress, uint256 _nftId) public {
tasks.push(Task(nextId, _stackAddress, _nftId));
nextId++;
}
function findIndex(uint _id) internal view returns (uint) {
for (uint i = 0; i < tasks.length; i++) {
if (tasks[i].id == _id) {
return i;
}
}
revert("Task not found");
}
function updateTask(uint _id, uint256 _stackAddress, uint256 _nftId) public {
uint index = findIndex(_id);
tasks[index].stackAddress = _stackAddress;
tasks[index].nftId = _nftId;
}
function readTask(uint _id) public view returns (uint, uint256, uint256) {
uint index = findIndex(_id);
return (tasks[index].id, tasks[index].stackAddress, tasks[index].nftId);
}
function deleteTask(uint _id) public {
uint index = findIndex(_id);
delete tasks[index];
}
}
You can return an array of structs:
function readAllTask() public view returns (Task[] memory) {
return tasks;
}
I think you have reason to do it, but just a remind that saving the data into blockchain is not a good deal, due to the high cost.
If you would like to return all the task, then simply make the tasks public. Solidity automatically assign a get function for it.
If you would like to get some specific content of task struct, then consider something like this:
function readAllTask() public view returns (uint, uint256, uint256 [] memory) {
// something
}

Gas Estimate of function: Infinite

Here's my first ever smart contract. What exactly causes such a warning and how should I improve my code?
This is just one of many similar warnings
Warning:
Gas requirement of function Consensus.deployPmu(string) high: infinite. If the gas requirement of a function is higher than the block gas limit, it cannot be executed. Please avoid loops in your functions or actions that modify large areas of storage (this includes clearing or copying arrays in storage)
pragma solidity ^0.5.7;
contract Consensus {
struct PMU{
string name;
address pmu;
uint256[] data;
bool errorFlag;
uint256 errorCount;
}
mapping (address => PMU) PMUS;
address[] accounts;
uint256[] empty;
function deployPmu(string memory _name) public{
PMUS[msg.sender] = PMU(_name,msg.sender,empty,false,0);
accounts.push(msg.sender);
}
function print() public view returns(string memory name, uint256[] memory data,bool errorFlag,uint256 errorCount){
PMU memory instancePMU = PMUS[msg.sender];
return (instancePMU.name,instancePMU.data,instancePMU.errorFlag,instancePMU.errorCount);
}
function log(uint256[] memory roc) public{
for (uint i=0; i<roc.length;i++){
PMUS[msg.sender].data.push(roc[i]);
if(roc[i]<12){
PMUS[msg.sender].errorFlag = false;
errorFlags[msg.sender] = false;
PMUS[msg.sender].errorCount=0;
}
if(roc[i]>12){
PMUS[msg.sender].errorCount= PMUS[msg.sender].errorCount+1;
}
if( PMUS[msg.sender].errorCount >= 5){
PMUS[msg.sender].errorFlag = true;
errorFlags[msg.sender] = true;
PMUS[msg.sender].errorCount = 0;
}
}
}
mapping (address => bool) errorFlags;
bool GridFault=false;
bool PMUfault=false;
address[] tru;
address[] falz;
function faultStatus () public returns (address[] memory)
{
address[] memory empty;
tru = empty;
falz =empty;
GridFault = false;
PMUfault = false;
uint256 count =0;
for(uint256 i =0; i<accounts.length; i++){
if(errorFlags[accounts[i]] == true){
count = count + 1;
tru.push(accounts[i]);
}
else{
falz.push(accounts[i]);
}
}
if(count > (accounts.length-1)/2){
GridFault = true;
if(falz.length != 0){
PMUfault = true;
}
}
else if(count == 0){
GridFault = false;
PMUfault = false;
}
else{
PMUfault = true;
return tru;
}
}
function gridstatus() public view returns(address[] memory, bool, bool){
if(GridFault == true){
return (falz,GridFault, PMUfault);
}
else{
return(tru,GridFault, PMUfault);
}
}
}

Solidity: Retrieving values of Array of Structs in Mapping

I have some solidity code where I am attempting to gather the ids which are a value stored on a Struct. I have a mapping where the key is an address, and the value is an array of Structs. Whenever I execute the getMediaByAddress function I get an invalid OpCode error. Any help would be greatly appreciated.
pragma solidity ^0.4.24;
contract MediaGallery {
address owner;
uint counter;
struct MediaAsset {
uint id;
string name;
address author;
uint createDate;
string[] tags;
string mediaHash;
}
mapping(address => MediaAsset[]) public mediaDatabase;
constructor () {
owner = msg.sender;
}
function addMedia(string _name, string _mediaHash) public returns (bool success) {
MediaAsset memory currentMedia;
currentMedia.id = counter;
currentMedia.name = _name;
currentMedia.author = msg.sender;
currentMedia.createDate = now;
currentMedia.mediaHash = _mediaHash;
mediaDatabase[msg.sender].push(currentMedia);
return true;
}
function addTag(uint _id, string _tag) public returns (bool success) {
mediaDatabase[msg.sender][_id].tags.push(_tag);
return true;
}
function getMediaByAddress(address _user) public view returns (uint[]) {
uint[] memory mediaAssetIds = new uint[](mediaDatabase[_user].length);
uint numberOfMediaAssets = 0;
for(uint i = 1; i <= mediaDatabase[_user].length; i++) {
mediaAssetIds[numberOfMediaAssets] = mediaDatabase[_user][i].id;
numberOfMediaAssets++;
}
return mediaAssetIds;
}
}
You're trying to read past the end of the array. Your loop variable i has an off-by-one error. Its greatest value is mediaDatabase[_user].length, which is 1 past the end of the array. Try this instead:
for (uint i = 0; i < mediaDatabase[_user].length; i++) {