- Lab
- Core Tech

Guided: Introduction to Solidity Development using Hardhat
In this hands-on lab, you'll dive deep into Ethereum blockchain development using Hardhat and Solidity. You'll engage with key elements like contracts, variables, functions, and unit testing. Through hands-on exercises, you'll create and test a simple contract, understand how variables are used to store and handle data, learn how to manipulate function visibility, and explore unique features of Solidity variables such as Ethereum address types. This lab offers a solid stepping stone to confidently develop robust and secure smart contracts.

Path Info
Table of Contents
-
Challenge
Introduction
Welcome to "Guided: Introduction to Solidity Development using Hardhat."
In this hands-on session, you'll embark on the journey of constructing a simple Solidity contract, enabling you to grasp the essential syntax and semantics of the Solidity language.
Solidity is a high-level, statically-typed programming language used for creating smart contracts on the Ethereum blockchain. These smart contracts are self-executing agreements embedded in code and are hosted on the Ethereum Virtual Machine (EVM), a decentralized runtime environment that executes these contracts.
The EVM is an essential component of the Ethereum network as it provides security and execution isolation to the smart contracts. It is completely sandboxed from the network, file system, and other processes of the host computer system.
Throughout your exploration, you'll be utilizing the Hardhat development environment. Hardhat is a development environment commonly used for Solidity development. It offers features for writing, compiling, debugging, and deploying your smart contracts and decentralized applications (dApps) within your local development environment. By providing an EVM tailored for development, Hardhat greatly streamlines the process of developing, deploying, and testing smart contracts in Solidity, making it a favored tool among Ethereum developers.
To facilitate a seamless learning experience, Hardhat has been pre-installed in the current environment. However, if you're interested in setting it up in your own workspace, you can follow the instructions provided at https://hardhat.org/hardhat-runner/docs/getting-started#installation.
When ready, click the Next step > button below.
-
Challenge
Building your First Contract
In the Hardhat development environment, Solidity contract source files are written in files that reside within the
contracts
directory and have a.sol
file extension. While Hardhat provides a conducive environment for developing and testing these contracts, the actual transformation of the contract code into EVM bytecode, which is the format executed on the Ethereum blockchain, is handled by the Solidity compiler.A Solidity source file begins with a
pragma
statement, a directive for the Solidity compiler indicating which version of Solidity is compatible with the code. This step is crucial because the Solidity compiler, although separate from Hardhat, can exhibit differences in behavior across versions due to its semantic versioning system. Thepragma
statement helps to ensure that the smart contract will not accidentally be compiled with a newer, potentially incompatible compiler. In addition to thepragma
statement, another line often found at the top of Solidity files is the SPDX-License-Identifier, such as// SPDX-License-Identifier: MIT
. This indicates the license under which the file is distributed. While not mandatory for the contract to function, it's highly recommended for open-source projects and is often required by tooling that interacts with Solidity code. If not provided Hardhat will throw a warning message when trying to compile the contract. Following these directives, the contract is declared using thecontract
keyword, followed by the contract's name. A contract in Solidity can be seen as analogous to a class in object-oriented programming languages. It serves as the primary building block of Ethereum applications — at its simplest, a single contract is a collection of code (its functions) and data (its state) that resides at a specific address on the Ethereum blockchain. In the following steps, you will delve deeper into the specifics of Solidity, learning to declare variables and define functions within your contract. This will provide you with the foundational knowledge needed to start creating your own fully-functional smart contracts.When ready, click the Next step > button below.
-
Challenge
Using Variables in Solidity for State and Data Management
In Solidity, variables play a critical role in storing and manipulating data within contracts. They accommodate a variety of data types, from primitive values to more complex user-defined structures.
Being a statically-typed language, Solidity demands that each variable's type be explicitly declared at its creation. This means the type of data a variable can hold is defined at compile-time, not at runtime. This static typing helps to catch errors early during development, as mismatches between declared and assigned types will trigger compiler errors.
Solidity provides several primitive data types like
string
,bool
, and integers (uint
,int
).Solidity offers a variety of primitive data types, such as string, bool, and integers. It's important to note that integers in Solidity come in two forms: unsigned (uint) and signed (int). Unsigned integers are always positive or zero, while signed integers can be negative, zero, or positive. Be careful when dealing with these types, as they have distinct properties and potential pitfalls, particularly regarding overflow and underflow conditions. More complex types, such as arrays (
[]
) andstruct
s, are also supported. Arrays store collections of homogeneous data, whilestruct
s enable creation of complex data types bundling variables of various types. Selecting suitable variable types is vital for efficient and secure contracts. Moreover, it's important to grasp the cost implications of different variable types.In Solidity, variables fall into two categories - state variables and local variables.
State variables, like the ones defined above, are declared outside any function within the contract. They represent the contract's state and are stored persistently on the Ethereum blockchain, preserving their values across transactions and function calls. However, this permanence comes with a cost. This cost is referred to as
gas
, which is Ethereum's unit of computational work. While efficient state variable management is key to optimizing contracts, an in-depth discussion ofgas
exceeds this lab's scope.Local variables, contrastingly, exist only within a function's scope. They are temporary, residing in memory and not on the blockchain. Their values reset every time the function is called, and manipulating them doesn't incur
gas
costs like state variables.Once ready, click the Next step > button below to explore functions and memory variables.
-
Challenge
Designing Functions for Dynamic Contract Operations
Functions are central to smart contract programming in Solidity. A function is a reusable piece of code that can be invoked from anywhere within a contract if visibility and access modifiers (like
public
,private
, etc.) allow it. Functions can take arguments, execute specific operations, and return results. Additionally, depending on the access modifier, functions can be called externally by account holders interacting with the contract on the blockchain.In Solidity, functions are declared with the
function
keyword, followed by the function name. The arguments are defined within parentheses()
, followed by any function modifiers, and then the body of the function, where the logic is written, is enclosed within curly braces{}
. The_age
parameter is of typeuint
, which is a value type in Solidity. Value types such asuint
orbool
create a new copy when they're assigned to another variable or passed as arguments to a function, so they don't reference the original variables or memory locations. Conversely, when a function accepts a reference type, like astring
or an array, the parameter must be marked with a data location keyword:memory
orcalldata
. These keywords dictate where the data for these reference types is stored during the function execution.Memory
denotes that the data is temporarily held in memory and will be discarded once the function call ends, whilecalldata
is read-only, more gas-efficient, and primarily used for data passed by external calls made into the contract.In addition to these data location keywords, Solidity also provides function modifiers of
view
andpure
.The
pure
modifier ensures the function will not read from or write to the contract's state.On the other hand, the
view
modifier ensures the function will not modify the contract's state. Also, observe how the return type(s) of the function are declared. A function can return more than one type. In subsequent steps, you will explore how these returned values can be consumed by the calling function.With your grasp of Solidity's fundamental elements like variables and functions, you're now prepared to immerse yourself in the unique aspects of blockchain development. To facilitate this process, you'll be engaging with Hardhat unit tests, an invaluable resource for investigating, validating, and testing the operations of your smart contracts.
When you are ready, click the Next step > button below.
-
Challenge
Leveraging Hardhat for Unit Testing Blockchain Specifics in Solidity Contracts
Hardhat unit testing serves as an integral component in blockchain development, particularly due to the immutable nature of smart contracts deployed on the Ethereum blockchain. Once deployed, these contracts cannot be modified, which underscores the critical need for testing prior to deployment. By writing and executing unit tests using Hardhat, developers can ensure the reliability and correctness of their smart contracts' code. These unit tests systematically verify the behavior of individual contract functions, validate contract logic, and help identify potential bugs or errors early in the development process. Hardhat's testing framework allows developers to simulate blockchain interactions, deploy contracts to a local development network, and validate contract functionality within a controlled environment. This introduction explores the benefits of using Hardhat for unit testing in blockchain development, enabling developers to confidently build robust and secure smart contracts.
Hardhat offers many helpers to test your smart contracts. One such feature is a local test Ethereum network. Launching this command fires up the local Ethereum network and creates a series of accounts for testing purposes. While the details of accounts is a bit beyond the scope of this lab, it's important to understand that the Ethereum network accommodates two distinct types of accounts. The first type is an Externally Owned Account, which is accessible by anyone possessing the private key of the account. The second type is a Contract Account, which is responsible for storing the specifics of a smart contract. To deepen your understanding of accounts, you may find this documentation useful: https://ethereum.org/en/developers/docs/accounts/
You can stop the running network by placing focus into the
Terminal
window and pressing theCtrl+c
keys.To unit test your smart contract, you need to deploy it to the Ethereum network and retrieve a reference to the created contract account. A Hardhat unit test is able to use this local test network for deployment. Hardhat also extends the ethers.js library with functionalities that aid interaction with the Ethereum network, such as the
deployContract
method that deploys this contract to the local network. Now, you can start writing unit tests against the deployed contract, such as verifying that thesetAge
function works correctly. > Notice the call to theage
variable. This is actually a call to a getter function that the solidity compiler created for you, implicitly exposing theage
variable as public. If you prefer the variable to be private, you can mark it asprivate
.You have now created your first unit test. The above unit test is an example of interacting with a Contract Account that is being referenced by the
firstContract
variable.To interact with an Externally Owned Account, the Hardhat-ethers plugin provides the
getSigners()
method. Scrolling up in theTerminal
window, you'll see all of the details for theowner
account, including its address. You'll also see that there are 19 other accounts added to the local test Ethereum network.With this introduction to working with Ethereum accounts, you're ready to explore Solidity-specific variables.
When ready, click the Next step > button below to explore
address
andmapping
variables. -
Challenge
Utilizing Address and Mapping Types in Solidity
In the Ethereum ecosystem,
address
andmapping
are two versatile variable types. Theaddress
type can hold the unique identifiers of both Externally Owned Accounts (EOA) and Contract Accounts, facilitating efficient interactions with users and contracts within the Ethereum network. When deploying a contract to the network, a unique type of transaction is initiated. This transaction must be initiated by an Externally Owned Account (EOA). Theconstructor
function, which is executed only once upon contract deployment, is used to initialize state variables. Ethereum transactions provide access to a special global variable,msg
, which contains details about the transaction. For instance,msg.sender
represents the address of the EOA initiating the current call. You can utilize thisowner
address to control who can change the state of the contract. For example, you may want to allow only the contract owner to change thename
variable. You can enforce this rule by checking ifmsg.sender
is equal toowner
: Alternatively, Solidity provides therequire
function to enforce conditions. Unlike theif
statement, arequire
function will stop execution and revert all changes if its condition is not met: Another key type of Solidity ismapping
, which allows you to store structured data much like a hash table or dictionary. For example, you can create a mapping of addresses to names: The combination ofaddress
andmapping
types enable developers to create engaging decentralized applications, from simple token contracts to complex voting systems, Decentralized Autonomous Organizations (DAOs) and more. These types allow developers to manage complex data relationships in a robust and gas-efficient way, crucial for the computational environment of Ethereum.When ready, click the Next step > below.
-
Challenge
Next Steps
Congratulations on completing this Introduction to Solidity Development using Hardhat.
You've taken a significant step forward in your blockchain journey. Don't stop here—continue experimenting with this lab and explore the vast possibilities this knowledge unlocks.
Some ideas are to:
- Enhance the contract by adding a
getMyName()
function that returns the name that is mapped to the calling account. - Create unit tests around the
address
andmapping
functions created in the previous step
As you become comfortable with Solidity syntax and learn to build and test smart contracts using Hardhat, you'll be ready to tackle more intricate concepts. Up next, delve deeper into Solidity's syntax and learn how to deploy your smart contract to a network.
Remember, learning is a journey, not a race. Each step you take brings you closer to becoming an accomplished blockchain developer.
The best to you as you continue your exciting journey into Blockchain training and Solidity contract development! We look forward to seeing what you will create.
- Enhance the contract by adding a
What's a lab?
Hands-on Labs are real environments created by industry experts to help you learn. These environments help you gain knowledge and experience, practice without compromising your system, test without risk, destroy without fear, and let you learn from your mistakes. Hands-on Labs: practice your skills before delivering in the real world.
Provided environment for hands-on practice
We will provide the credentials and environment necessary for you to practice right within your browser.
Guided walkthrough
Follow along with the author’s guided walkthrough and build something new in your provided environment!
Did you know?
On average, you retain 75% more of your learning if you get time for practice.