Help! How to loop through an array of Addresses?

Can someone please help me figure out how to loop through an array of addresses. To me it looks like the code should work, but it does not and I have no idea why.

The array is being looped through to check if the customers wallet address exists inside the array

bool customerWalletPreApproval = false;
address[] preApprovedAddresses = [
            0xdD870fA1b7C4700F2BD7f44238821C26f7392148,
            0x03C6FcED478cBbC9a4FAB34eF9f40767739D1Ff7,
            0x583031D1113aD414F02576BD6afaBfb302140225,
            0x0A098Eda01Ce92ff4A4CCb7A4fFFb5A43EBC70DC
        ];

function customerWallet(address _customerWallet) public returns  (string memory message) {
        for(uint i = 0; i < preApprovedAddresses.length; i++){
            if(_customerWallet == preApprovedAddresses[i]){
                customerWalletPreApproval = true;
                message = "Congratulations your wallet is on the pre-approved list for minting";
            }
            else if(_customerWallet != preApprovedAddresses[i]){
                message = "Unfortunately your wallet is not pre-approved for minting";
            }
        }
    }

Hi @obikodi,

Your loop works just fine. But I would suggest changing it like that:

pragma solidity 0.8.10;

contract Test {
    bool customerWalletPreApproval = false;
    address[] preApprovedAddresses = [
        0x5B38Da6a701c568545dCfcB03FcB875f56beddC4,
        0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2,
        0x4B20993Bc481177ec7E8f571ceCaE8A9e22C02db,
        0x78731D3Ca6b7E34aC0F824c42a7cC18A495cabaB
    ];

    function customerWallet(address _customerWallet) public returns  (string memory message) {
            for(uint i = 0; i < preApprovedAddresses.length; i++){
                if(_customerWallet == preApprovedAddresses[i]){
                    customerWalletPreApproval = true;
                    message = "Congratulations your wallet is on the pre-approved list for minting";
                    break;
                } else {
                    message = "Unfortunately your wallet is not pre-approved for minting";
                }
            }
        }
}
  1. You don’t need to have else if (statement) because you’re only testing two conditions, true or false. And if it’s not true, then it’s 100% false.

  2. If you add a break; then the loop will break and finish, and that’s what you might want. Because you are checking just one address at a time. There is no need to continue looping though the rest, since it’s been found already. That’s why the customerWalletPreApproval was true, but sill the message was "Unfortunately your wallet is not pre-approved for minting".

2 Likes

Thank you for your reply, I will try this out and get back to you with my findings. Cheers.

Bro you’re a genius. That break was the magic spice i needed to make this whole code work like butter. Thank you my man. Was bustin my head for hours tryna figure this out.

1 Like

Hey @obikodi & @JJ_FX,

You should also omit the else statement from the for-loop, because you don’t need to conclude that the customer address isn’t in the array until all of the addresses have been iterated over. This will simplify your code and make it clearer.

Also, using break isn’t necessary if you use return statements to exit the function (and output the appropriate message) whenever the outcome has been established. e.g.

function customerWallet(address _customerWallet) public returns (string memory) {
    for(uint i = 0; i < preApprovedAddresses.length; i++) {
        if(_customerWallet == preApprovedAddresses[i]) {
            customerWalletPreApproval = true;
            return "Congratulations your wallet is on the pre-approved list for minting";
        }
    }
    return "Unfortunately your wallet is not pre-approved for minting";
}

If the function is called with a pre-approved address, the Boolean state variable customerWalletPreApproval is set to true. However, if the next address to call the function is not pre-approved, the correct message is output, but customerWalletPreApproval remains true. Is this what you intend? Without knowing the role this Boolean state variable plays in the context of your full contract, I can’t say whether this is correct or not, but it does seem strange, so I thought I’d just mention it.

Let me know if you have any questions :slight_smile:

2 Likes

Good point @jon_m :grinning:

2 Likes

Hi Jon, thanks for taking the time to look into this.

So the way the code was intended to work is that the boolean customerWalletPreApproval should only be set to true if the customer wallet is on the pre approval list / array.

So if i’m understanding your questioning on this part of the function correctly, did i write this wrong?

Because I am calling this function every time an address is entered into the dapp, because each address needs to be checked through this function. But the way ive written it, once the customerWalletPreApproval bool is set to true, then every address checked thereafter will automatically be set to true as well? Is that what you’re saying?

If that’s true then i’m thinking I still need to keep the else if statement in there, but update it to include something like - customerWalletPreApproval = false;. So that way when another address gets checked, the bool has the opportunity to be updated according to that address and if it meets the conditions of the if statement?

Ehh I feel like i’m just guessing my way through all this right now but I genuinely appreciate you taking the time to help me out. Thanks Jon, and also thank you JJ.

1 Like

Yes, that’s what I mean. But my question would be, does this pre-approval indicator (true or false) need to be saved in a state variable? This will depend on how you’re using it once it’s been set. I assume you must be using it in an operation which immediately follows the execution of customerWallet(), because as soon as customerWallet() is called with another address, this same state variable needs to record this new address’s pre-approval status, effectively overwriting that of the previous address that was checked.

If you need to save each address’s pre-approval status (as determined by the customerWallet function), and not keep overwriting it, you will probably need a mapping e.g.

mapping(address => bool) customerpreApproval;

This also allows an address that was previously not pre-approved to have its status updated from false to true if it has since been pre-approved and added to the preApprovedAddresses array.

If, on the other hand, you don’t need to store an address’s pre-approval status persistently, you probably don’t need a state variable anyway. Instead, you could pass the Boolean to another function and use it there.

You can just add   customerWalletPreApproval = false;   after the for-loop as well. Both this and the return statement for the message only need to be executed once, if the address has not been found in the array e.g.

function customerWallet(address _customerWallet) public returns (string memory) {
    for(uint i = 0; i < preApprovedAddresses.length; i++) {
        if(_customerWallet == preApprovedAddresses[i]) {
            customerWalletPreApproval = true;
            // customerWalletPreApproval[_customerWallet] = true;  (if use mapping)
            return "Congratulations your wallet is on the pre-approved list for minting";
        }
    }
    customerWalletPreApproval = false;
    // customerWalletPreApproval[_customerWallet] = false;  (if use mapping)
    return "Unfortunately your wallet is not pre-approved for minting";
}

Just let me know if you have any more questions :slight_smile:

2 Likes

Extremely helpful Jon, I ended up updating my code based on your recommendations, I much preferred your logic and coding solution, leaner is greener :slight_smile:

You’ve restored my faith in this forum and I will now be posting all my problems on here moving forward lol.

Thank you very much!

1 Like