DEV Community

Cover image for Understanding mappings in Solidity
Murat Can Yüksel
Murat Can Yüksel

Posted on

Understanding mappings in Solidity

If you're a Javascript developer and learning Solidity now, you've probably realized that mappings are weird.

I've had serious troubles wrapping my head round this way of structuring data.

If you go to solidity-by-example.org, you'll see that mappings are defined like so :

Maps are created with the syntax mapping(keyType => valueType).

The keyType can be any built-in value type, bytes, string, or any contract.

valueType can be any type including another mapping or an array.

Mappings are not iterable.
Enter fullscreen mode Exit fullscreen mode

Nice, let's see them in action so that we can understand them better.

In my last Solidity project where I built a voting dApp, I wanted to keep track of all the addresses that had voted for a proposal because each address could only vote once per proposal. I created a mapping to do this :

mapping(uint256 => mapping(address => bool)) private hasVotedForProposal;

What the hell, bro? Let me explain.

As mappings valueTypes can be any type, including mappings, I'm creating a nested mapping. If I tried to translate it into human language, I'd probably read it as such: Create a private variable, that is a mapping, named hasVotedForProposal, it should map a uint256 type (that is a number in the simplest sense, that is linked to another mapping that links an address to a boolean value.

What?

The way I'm using it, I have a proposal struct (basically an object in JS) and that proposal has an id. I'm also saving my proposals in a proposals array.

So, when a user votes for a proposal, I'm checking if they have already voted for that proposal by checking if the address is in the mapping. If it is, I'm not allowing them to vote again. If it's not, I'm allowing them to vote.

In order to do that, I have a vote function and when a user calls that vote function, I'm passing the proposal id as an argument. => hasVotedForProposal[_proposalId][msg.sender] = true;

Note that msg.sender is the address of the user that is calling the function.

Here, I invoke the hasVotedForProposal mapping and pass the proposal id as the first argument (that first uin256 that is linked to the 2nd mapping) so that whenever I want to check this id in the hasVotedForProposal mapping, it'll show the 2nd mapping, which is the one that links the address (msg.sender) to the boolean value.

I hope this helps you understand mappings better. If you have any questions, feel free to ask them in the comments.

Top comments (0)