0

I'm trying to map the address with the account name, but with the find_user_name function in my contract, it keeps showing the Gas estimation failed while deploying the contract. I have the struct user:

 struct user{
        string account;
        string password;
        address useraddress;
    }

and initialize the userlist

user[] public userlist;

then I write the find_user_name function to map to address with the account

 //return the user name by mapping the address
    function find_user_name(address _address) public view returns(string){
      uint256 i;
      string account_name;
      for(i=0; i < userlist.length; i++){//find the mapping user account name
            if(_address == userlist[i].useraddress)account_name = userlist[i].account;
      }

      return account_name;
    }

Is there anything wrong with my logic? Otherwise It sholud be okay when deploying the contract..

Rob Hitchens
  • 55,151
  • 11
  • 89
  • 145
  • On a side note, I hope that you aren't deploying a contract storing passwords to a public blockchain like Ethereum's blockchain. All unencrypted strings stored on the blockchain are out in full view, so aren't actually secure. Also, even an encrypted password stored on the blockchain in a contract would be subject to dictionary attacks. – Ether Dude May 28 '18 at 20:11

2 Answers2

2

This is no good because the for loop will run out of gas at some scale ... that is, at some point the cost per iteration times the number of iterations will exceed the block gas limit. That would be catastrophic because it would mean that the contract simply stops working after max users pile in.

You want the Mapped Struct with Index pattern over here: Are there well-solved and simple storage patterns for Solidity?

This will let you perform lookups in one move (a minimum requirement for scale), as well as iterate the keys. Also, have a look over here for a more verbose and complete explanation: https://medium.com/@robhitchens/solidity-crud-part-1-824ffa69509a

Hope it helps.

Rob Hitchens
  • 55,151
  • 11
  • 89
  • 145
  • I think mapping will work. But now I have the userlist, is there anyway I can transfer the data in the userlist directly into a mapping? – 2341047123413331 May 29 '18 at 00:10
  • Sorry. I don't understand what you mean by transferring the data. This is pre-deployment so there is no data. You want to map the structs with mapping(address=>UserStruct) public userStructs and you can also keep a list of keys in address[] public userAddresses if you will need to enumerate user ids. – Rob Hitchens May 29 '18 at 02:12
  • Thanks Rob I get it. I enumerate a new mapping to store the data that are already in the userlist – 2341047123413331 May 29 '18 at 06:23
0

You can do this with a mapping of structs, avoid complexity, and avoid as well future problems as the number of users increases.

struct user{
        string account;
        string password;
        address useraddress;
    }

mapping(address => user)  public userlist;

function find_user_name(address _address) public view returns(string){      
      return userlist[_address].account;
    }

Hope this helps

Jaime
  • 8,340
  • 1
  • 12
  • 20