Learning Objectives – after this chapter you will be able to:
- Declare and use mappings, including nested mappings.
- State which key and value types are allowed.
- Explain default values, getters and why mappings cannot be iterated or measured.
- Combine a mapping with an array to make data iterable.
Mapping
- A mapping stores data as key → value pairs, like a hash table or dictionary in other languages. A common example links Ethereum addresses to balances.
- Think of a mapping as a table in which every possible key already exists and initially holds the default value of the value type (0, false, empty string …).
Syntax
mapping(KeyType => ValueType) <visibility> <name>; mapping(address => uint) public balances; mapping(address user => uint balance) public named; // named keys/values (0.8.18+)
- KeyType − any built-in value type (
uint,address,bool,bytes32…),bytes,string, a contract type or an enum. Mappings, structs and arrays cannot be keys. - ValueType − any type, including structs, arrays and other mappings.
Please Note
- Mappings can only be stored in storage – they are used as state variables (or storage references). They cannot be created in memory.
- A mapping can be marked
public; Solidity then creates a getter that takes the key as a parameter, e.g.balances(addr). - The keys themselves are not stored; the value’s location is calculated from the hash (keccak256) of the key. Therefore a mapping has no length and cannot be iterated.
- You cannot tell whether a key was “set to 0” or “never set” – both read as 0. Use an extra
boolor a struct field if you need to know. delete balances[addr]resets that key’s value to the default.
Nested Mappings
The value of a mapping can itself be a mapping – for example, how much each owner allows each spender to use (the ERC-20 allowance pattern):
mapping(address => mapping(address => uint)) public allowance; // allowance[owner][spender] = amount;
Example : Student Marks Register
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract MarksRegister {
mapping(uint => uint) public marksOf; // roll number => marks
mapping(uint => bool) public isRegistered; // to tell "0 marks" from "not set"
mapping(address => mapping(uint => bool)) public canEdit; // nested mapping
uint[] public rollNumbers; // array of keys => makes data iterable
address public teacher;
constructor() {
teacher = msg.sender;
}
function setMarks(uint roll, uint marks) external {
require(msg.sender == teacher || canEdit[msg.sender][roll], "Not allowed");
if (!isRegistered[roll]) {
isRegistered[roll] = true;
rollNumbers.push(roll);
}
marksOf[roll] = marks;
}
function allowEditor(address editor, uint roll) external {
require(msg.sender == teacher, "Only teacher");
canEdit[editor][roll] = true;
}
function totalMarks() external view returns (uint total) {
for (uint i = 0; i < rollNumbers.length; i++) {
total += marksOf[rollNumbers[i]];
}
}
function removeMarks(uint roll) external {
require(msg.sender == teacher, "Only teacher");
delete marksOf[roll]; // value back to 0
}
}
Key Takeaways
mapping(Key => Value)gives fast key look-ups; every key starts at the default value.- Mappings live only in storage, have no length and cannot be looped over directly.
- Keep a separate array of keys (or a flag) when you need to iterate or detect unset keys.
Download | Print E-Notes
The PDF E-Notes are the earlier printable version of this chapter. The notes on this page are the latest, revised version.
Question / Answer (15 questions)
Answer : Like a hash table or dictionary, a mapping stores key-value pairs and gives direct access to a value by its key. The location of each value is computed from a hash (keccak256) of the key.
Answer :
mapping(KeyType => ValueType) visibility name;, for example mapping(address => uint) public balances;.Answer : Any built-in value type (uint, address, bool, bytes32 …), bytes, string, contract types and enums. Mappings, structs and arrays cannot be used as keys.
Answer : Any type, including structs, arrays and other mappings.
Answer : The default value of the value type – for example 0 for uint, false for bool or the zero address for address.
Answer : The keys are not stored; only values are stored at locations derived from key hashes. Since the contract does not know which keys were used, it cannot count or iterate them.
Answer : Maintain a separate array that stores every key when it is first added, then loop over the array and read each key’s value from the mapping.
Answer : Only storage. Mappings are used as state variables or storage references and cannot be created in memory.
Answer : An external view function
balances(address) that takes a key and returns the corresponding value.Answer : A mapping whose value type is another mapping, e.g.
mapping(address => mapping(address => uint)) allowance;, used in ERC-20 tokens to store how much each owner allows each spender to use.Answer : Both read as 0, so store extra information such as a separate
mapping(key => bool) isRegistered or a struct with an exists flag.Answer : It resets the value for that key to its default (0). The key itself is not “removed” because keys are never stored.
Answer : Since Solidity 0.8.18 you can name the key and value for readability, e.g.
mapping(address user => uint balance) balances;. The names do not change behaviour.Answer : A mapping finds a value directly in constant time and cost, while searching an array requires a loop whose gas cost grows with the array size.
Answer : It records each registered roll number so that totalMarks() can loop over all keys, something the mapping alone cannot do.
MCQ Test : Check Your Understanding (5 questions)
Select an option and press Check Answer, or answer all questions and press Submit Test to see your score. Each answer comes with an explanation.
Bibliography/References
The notes, questions and MCQs on this page are original explanations written for this course. The works listed below were consulted and are cited for attribution and further reading. Product names, logos and trademarks belong to their respective owners. Short quotations, where used, are marked and attributed.
- Solidity Team. (n.d.). Types (value types, reference types, mappings, operators, conversions). Solidity Documentation. https://docs.soliditylang.org/en/latest/types.html
- Solidity Team. (n.d.). Layout of State Variables in Storage. Solidity Documentation. https://docs.soliditylang.org/en/latest/internals/layout_in_storage.html
- Vogelsteller, F., & Buterin, V. (2015). ERC-20: Token Standard. Ethereum Improvement Proposals, no. 20. https://eips.ethereum.org/EIPS/eip-20
- Solidity Team. (n.d.). Cheatsheet. Solidity Documentation. https://docs.soliditylang.org/en/latest/cheatsheet.html
- Modi, R. (2018). Solidity Programming Essentials: A beginner’s guide to build smart contracts for Ethereum and blockchain. Packt Publishing. ISBN 978-1-78883-138-3.