1

I just tarted to write solidity and i have some questions that i could not find the answer to.

When you declare a map like this:

struct UserAccount{
    string name;
    uint id;
}

mapping (address => UserAccount) public accounts;

How will that be initialised? or with what?

For example, accessing

accounts[0x79d66c53ad6f1847288c0d06c01a2b38c38f15bc]

will return an instance of an UserAccount? If yes, that means that the map creates an instance of UserAccount for every possible address? Doesn't that consume very much memory? If not, then how comes you can do this:

accounts[_address].name = _name;

?

And the second question:

I keep reference in my contract of an address that is the owner, the address that created the contract:

address public owner;
constructor() public {
    owner = msg.sender;
}

After i call this function:

uint userCount=0;
mapping (address => UserAccount) public accounts;

function createAccount(string _name, uint _id, address _address) onlyOwner() public {
    UserAccount user;
    user.name = _name;
    user.id = _id;
    accounts[_address] = user;
    userCount += 1;
    // accounts[_address].name = _name;
    // accounts[_address].id = _id;
    // userCount += 1;
    emit UserCreated(_address, _id, _name);
}

modifier onlyOwner() {
    require(msg.sender == owner);
    _;        
}

the owner address changes. The commented lines from createAccount function are the way to do it, i know, but i want to understand why it does not work.

To clarify my problem i will also post a js test.

beforeEach(async () => {
    voting = await Voting.new({from: owner});
});

it("Should delete poll, as owner", async () =>{
    var name = "Sandu";
    console.log("LOCAL OWNER= " + owner);
    console.log("OWNER BEFORE CREATE ACCOUNT FROM SOL= " + await voting.owner());
    await voting.createAccount(name, 1, firstUser,{from:owner});
    console.log("OWNER AFTER CREATE ACCOUNT FROM SOL= " + await voting.owner());
    var pollName = "First Poll";
    var endDateS="2018-08-11T10:20:30Z";
    var endDate=new Date(endDateS)
    await voting.createPoll(pollName, 1, endDate.getTime()/1000,{from:firstUser});


    try{
        await voting.deletePollById(1,{from: owner});
    }catch(err){
        console.log(err.message);
    }

    assert.notEqual(pollName, await voting.getPollById(1));
});

The test above prints this:

LOCAL OWNER= 0x79d66c53ad6f1847288c0d06c01a2b38c38f15bc //Owner that o have in my js file local, first address from the ganache accounts.
OWNER BEFORE CREATE ACCOUNT FROM SOL= 0x79d66c53ad6f1847288c0d06c01a2b38c38f15bc  //The owner account from my contract before calling the function
OWNER AFTER CREATE ACCOUNT FROM SOL= 0x000000000000000000000000000000000000000a   //The owner account from my contract after calling the function

I can't understand why the value from owner changes as i don't touch that in my function.

If anyone can help it would be much appreciated. Again, i know the right way to do it but i am posting this out of the desire to understand what i am doing not to get the job done.

  • Alexandru, you should divide this into several questions. – Jaime Jun 19 '18 at 12:21
  • They are somehow connected, alone most of them don't make sens in my opinion – Alexandru Sandu Jun 19 '18 at 12:22
  • If you want to get as much help as possible you need to focus your questions, I think this is way too much for a single post. – Jaime Jun 19 '18 at 12:41
2

I would suggest that you check Solidity documentation.

Here are relevant locations:

In short: there is no initialization of the record/mapping. Virtually all records are pre-initialized with zeros and are already existent.

A common pattern how it's done is sketched here:

function createAccount(string _name, uint _id, address _address) onlyOwner() public {
    UserAccount storage user = accounts[_address];

    require(user.id == 0);

    user.name = _name;
    user.id = _id;

    userCount += 1;

    emit UserCreated(_address, _id, _name);
}
  • Doesn't that use more gas than not keeping the reference of the accounts[_address] into user? Meaning you will not create a storage variable, just call aaccounts[_address].name=_name etc.. – Alexandru Sandu Jun 19 '18 at 13:21
  • Thx for the documentation, it was quite usefull, it answers some of my questions – Alexandru Sandu Jun 19 '18 at 13:22
  • You can think of UserAccount storage user = accounts[_address]; as reference to the storage. It's not like the whole record is copied. See storage modifier in documentation. – ivicaa Jun 19 '18 at 13:27
  • Thx, you were quite helpfull. I wont accept your answer yet tho, because then the rest od the questions will remail unanswered. I promise i will eventually. – Alexandru Sandu Jun 19 '18 at 13:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.