In week 5 of Alchemy University’s Ethereum Bootcamp, the material dives deeper into Solidity. Building on smart contract basics, more advanced topics are explored. Students learn about mappings, events, and the reference types arrays and structs. Understanding the details of these data types are essential in reading and creating smart contracts.
Mappings
Hash Tables
Understanding mappings in Solidity is easier to process with a knowledge of hash tables. A hash table is a type of data structure that implements an associative array. Data is stored as a collection of key-value pairs. A key represents some data to be stored. The key is fed into an algorithm which produces a hash value. The hash value dictates the index where the data associated with the key will be stored. Hash tables are extremely efficient for looking up data. The same key always returns the same value.
Mappings
In solidity, hash tables are known as mappings. A key is associated to a corresponding value. Mappings are declared like other variables types in Solidity:
The mapping
keywords indicates a mapping is to be created. In the example above, _KeyType
is the key and the arrow =>
points to its value, _ValueType
. These key value pairs are stored inside the mapping named mappingName
.
Useful for Address Association
Mappings are useful for address association. Mappings make it easy to associate an Ethereum address with a value. In the example below, a mapping is created to keep track of how many sodas a specific address has purchased:
Using the address as a key, a function can be used to extract the associated value:
The function above takes an address as a parameter. The function returns a uint
which is a value associated with the address used as the function parameter. Using the sodasPurchased
mapping created earlier, the address input is used with brackets to retrieve its associated value.
Mappings can have many use cases. Any type of data that needs a key-value pair form of tracking would be ideal to use with mappings:
Nested Mapping
Mappings can keep track of multiple associations through nesting.
In the example above, an address is mapped to an association between a uint
key and bool
value. This example would be a way to track whether an address voted on a proposal.
Mappings are very useful and important to understand. Understanding mappings gives developers an efficient way to track data. Creating associations can be a powerful tool when using Ethereum addresses.
Events
Introduction to Events
Events are a way to log information about a smart contract onto the blockchain. Events are an abstraction on top of the EVM’s low-level logging functionality through log opcodes. The low-level logs are stored in the transaction receipt. Logs are written by smart contracts when they emit events, but logs cannot be read by smart contracts. Logs serve the purpose of storing data on chain in a searchable and gas efficient way.
Defining Events
Events are defined in a smart contract using the event
keyword.
In the snippet above, an event is named Transfer.
The event has three topics: from
, to
, and value
. When the Transfer
event is emitted, the from
, to
, and value
data will all be included in the event. Code that is listening for the event will be able to filter topics that have the indexed
keyword.
Emitting Events
After an event is defined, the next step is to emit the event.
Listening to Events
Smart contracts can write events, but they cannot read them. In order to do so, a library like ethers.js can be used. Ethers.js allows the use of a provider class which can connect to the smart contract.
Finding Events in Logs
While using ethers.js abstracts away low level code, the eth_getLogs method interacts directly with Ethereum’s JSON-RPC endpoint. Using this lower-level method, a loop would be needed in order to parse through all the information retrieved to narrow down the address in question. This highlights one of the benefits of using a library like ethers.js as there is no need for a loop.
Events and logs are stored on the blockchain in transaction receipts, but they are not required for blockchain consensus. Because events are stored in transaction receipts, they are verified by the blockchain even though events are not a requirement for consensus. Events are the ideal way to emit occurrences on the blockchain to the outside world.
Reference Types: Arrays and Structs
Solidity Reference types
Primitive data types in Solidity include uint/int
, boolean
, address
, enum
, and bytes
. Primitive types are also referred to as value types, and they store data directly in a variable. Solidity also has reference based data types which include arrays
, strings
, structs
, and mappings
. A reference type does not store values directly in a variable. Reference types hold a pointer to the address of the data’s location. The important concept to understand is that primitive types hold value directly while reference types point to a data location that holds the value.
Arrays
In computer science, an array is a data structure consisting of a collection of elements that are each identified by at least one array index or key. Arrays in Solidity behave like arrays in other programming languages. Solidity has both fixed and dynamic sized arrays.
Dynamic and Fixed Arrays
Dynamic arrays do not have a fixed size when they are defined. Elements can be added and the size of the dynamic array will change. Fixed arrays have a predetermined size. The amount of elements in a fixed array cannot exceed the size of the array.
Storage arrays
Storage arrays are typically declared as a state variable and they can be either fixed or dynamic in size. Both fixed and dynamic arrays have access to the .length
method which returns how many values an array holds per index. Dynamic storage arrays also have typical array methods such as .push()
and .pop()
. .push()
adds an element to the last position while .pop()
removes the last element from an array.
Structs
Structs are a feature of Solidity that allow developers to define their own data type. Structs are most often used to represent a grouping of common data. Structs are declared similar to object declarations in JavaScript.
Arrays and Struct Use Case
The concept of a struct and the usage of arrays can be exemplified through a Library smart contract. To keep track of books, a Book struct can be used to define a book by title, author, and id.
The struct keeps track of a single book. Single books would then be placed into a books
array.
In order to add a book, a function can be used that would take arguments to satisfy the parameters of the Book
struct.
In the snippet above, the add function takes two arguments. Both arguments are strings. When reference types are used as parameters for a function, they must be qualified by a data location declaration. Inside the function, the push method is used to push the book into the books
array. The Book
struct is initialized with three arguments as it is pushed into the books
array.
Structs are an extremely useful data type that developers should familiarize themselves with. As they are a custom data type, structs provide developers with flexibility when storing data. They are best utilized when grouping related data together. Structs can be declared outside of a contract and imported in another contract.
Conclusion
After completing week 5 of Alchemy University’s Ethereum Bootcamp, students are equipped with advanced Solidity knowledge. Building on the fundamental topics explored in earlier weeks, students learn more complex Solidity data types. In Solidity, mappings function as hash tables which are ideal for creating key-value pairs. Events allow developers to monitor the changes that occur on the blockchain. Arrays offer a way to store data while structs provide a custom data type ideal for grouping related data. The concepts covered provide developers with a strong foundation to understand and create smart contracts.