The easiest way to learn Solidity for beginners is to use a Solidity Tutorial. We have prepared an overview of the most important topics regarding the Solidity programming language. 2022 might be the best year to learn blockchain development because it enables you to build solutions for DAPPS, DEFI, and NFTs - in short build the future.
Update: Ethereum launched the Sepolia Testnet in 2022, learn how to deploy smart contracts to Sepolia Testnet.
What is Solidity?
Solidity is a programming language for smart contracts. It is most commonly used to write smart contracts for the Ethereum blockchain but it can be used to deploy smart contracts on any blockchain that uses the Ethereum Virtual Machine (EVM). There are different test nets that can be used before deploying to the mainnet like Sepolia, Goerli, Roposten, Rinkeby, and Kovan. By learning Solidity you will also be able to deploy contracts to the Binance Smart Chain (BSC), Polygon, Avalanche, Optimism, Gnosis, and others.
Solidity is a statically typed and object-oriented language. It is a high-level language that is compiled to bytecode for the Ethereum Virtual Machine (EVM bytecode). Solidity uses the Contract Application Binary Interface (ABI) to interact with smart contracts on the blockchain. Contracts are stored in files using the file ending .sol and have to be compiled by the Solidity compiler before they can be deployed to the blockchain.
The most common use cases are DAPPS, DEFI, and NFTs. What exactly can we build with Solidity? It can be used to create smart contracts for Ether Wallets, Multi-Sig Wallets, ERC20 tokens, and ERC721 tokens (NFTs). It is also possible to write contracts for English Auction, Dutch Auction, and Crowdfunding. TimeLock is another contract example that is most common in use by DAOs.
Is Solidity easy to learn?
Solidity is very similar to other programming languages like JavaScript, so if you have already prior knowledge it will be much easier for you to learn Solidity. For example Solidity uses Function Modifiers that are comparable to decorators in the Python programming language.
How long will it take to learn Solidity? It depends mostly on your experience, effort, and the right learning resources. To learn the basics of Solidity might take around 1 month and to become proficient in writing smart contracts in Solidity it might take between 3 to 6 months. Most people should be able to get job-ready for a career in web3 within a period of 12 months.
Salary of a Solidity developer
Blockchain developers are in high demand and Solidity is a valuable skill to have in the workplace. The salaries for Solidity developers are sky-high because the balance between supply and demand is highly skewed. There are just not enough developers with Solidity skills to fill open positions. The average Solidity Developer Salary is estimated to be above $100,000 per year. This is supplemented by other cool perks like being paid in crypto, working remote, and bonuses. For Solidity developers with a few years of experience and the ability to lead teams, the salary can climb even higher to $200,000-$400,000. In the end, it all comes down to your skill level, experience, and the value you can create for the company you are going to work for.
Another way to make money using Solidity skills is to participate in bug bounties that can pay millions of dollars in rewards for critical security vulnerabilities. To become a Solidity security expert it is important to understand previous attacks and think like a hacker. Security auditing of smart contracts is one of the most lucrative skills in the blockchain world.
Hello World
To get started learning Solidity our goal is to print "hello world". This can be done by the following code:
// SPDX-License-Identifier: MITpragma solidity ^0.8.7;
contract HelloWorld {
string public greet = "Hello World! :)";
}
The code includes an SPDX License Identifier in the first line, which specifies the license of our code. The license identifier is written as comment, which is indicated by two slashes //.
The second line specifies the compiler version our code is written for, it is called the pragma directive in Solidity. The first two lines should be on the top of every Solidity file a developer is writing.
Then we declare a new contract named HelloWorld. A contract is like a class in other Programming languages. Inside the contract we define a variable: The variable is of type string, the data type of our variable. We have to define the data type at the declaration of our variables, because Solidity is a statically typed language. The variable has the visibility public, which means we can later see the value of it in remix. And the variable has the name greet and the value "Hello World! :)".
To compile and deploy the code we can use an IDE. The best Solidity IDE for beginners is remix because you can do everything online in your browser without installing new software or compilers on your computer. Learn more about running the Hello World Script in the linked article.
Comments in Solidity
In Solidity comments can span over a single line or multiple lines. To create a single-line comment, use double slashes // and the line will be commented out.
// This is a single-line comment in Solidity.
To create a multi-line comment we use /* to start the comment and */ to end the comment. This is the same syntax that is used in other programming languages like JavaScript or even in Style Sheet languages like CSS.
/*
This is a multi-line
comment in Solidity
spanning over 3 lines
*/
Solidity also supports NatSpec Comments that are used for rich documentation. NatSpec stands for Ethereum Natural Language Specification Format and allows to document functions, events and other objects in Solidity.
Data Types in Solidity
Data types in Solidity can be categorized into two groups: value types and reference types. The value types like boolean, integer, address and enum store the actual value. The reference types like arrays, structs and mappings on the other hand only store a reference to the memory location of the value. So if a value type is changed, the actual value changes but if a reference type changes the original value is still unchanged. The data types string and bytes are also reference types unlike in other smart contract languages like Vyper.
Solidity is a statically-typed language, which means that the data type of every variable is known at compile time. The data type has to be defined by the developer when the variable is declared.
Solidity also supports hash functions that are commonly used to verify signatures. The keccak256 hash function returns a unique and fixed-sized bytes32 data type for the given input.
Variables in Solidity
Solidity knows three types of variables: state variables, local variables and global variables. The state variables store data on the blockchain and are persistent. They are declared inside a contract block but outside of functions. Local variables are declared within functions and have a local scope. They only exist within the function they are declared in. The global variables contain data about the blockchain like the sender of the message, the current block number or the block timestamp.
When naming variables and functions it is important to respect reserved keywords and not use them as identifiers. Otherwise, a DeclarationError is raised.
Constructor in Solidity
The constructor is a special function in Solidity. It is called only once, at the deployment of the contract. It is optional to have a constructor but every contract can not have multiple constructors. Constructors are usually used to initialize state variables and set ownership.
Events in Solidity
Solidity supports events similar to other programming languages. They can be used to communicate with the front-end of the application or to log data to the blockchain. Events are declared using the event keyword and triggered using emit. In the following example, the address of the caller of a transaction and the transaction amount is collected by the event.
// events in Solidity// declare an eventevent Test(addressindexed _from, uint _value);
// emit eventemit Test(msg.sender, msg.value);
Events allow us to store data on the blockchain, but the data can not be retrieved from the blockchain later. Up to three parameters of the event can be indexed.
Constants in Solidity
Constants are used when it is clear that a value will never change. It is common practice to write constants in uppercase letters and separate words in the constant identifier by using underscores. A constant is usually used to save gas and optimize the gas usage of a contract. How much gas can be saved using constants in Solidity? In our example, we saved 10% gas in comparison to using variables.
// SPDX-License-Identifier: MITpragma solidity ^0.8.7;
contract Constants {
addresspublicconstant MY_CONSTANT = 0x0000000000000000000000000000000000000000;
}
import in Solidity
To import another file in Solidity we can use a simple import statement.
import"filename";
It is also possible to import files from external sources like github. For example, we can import the Open Zeppelin SafeMath library. The SafeMath library is used for Solidity versions below 0.8 to prevent over- and underflows of integers.
import"https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v3.4/contracts/math/SafeMath.sol";
It is also possible to declare a new symbol to prevent naming collisions and keep the namespace clean. The objects from the imported file can then be called using the dot syntax: newSymbol.example();
import * as newSymbol from "filename";
Error handling in Solidity
There are three types of errors in Solidity: require is mostly used to validate inputs, revert doesn't evaluate anything is used with other conditions like an if else statement and assert checks if value is true. Since Solidity version 0.8 it is also possible to use custom errors. The big advantage of using custom errors, is that the allow us to save gas. This is possible because the gas costs of errors depend on the length of the error message.
Loops
Solidity supports looping concepts known from other programming languages, but they should be used carefully. In contrast to a program run on a centralized server the loops run on the blockchain can be very expensive in gas consumption. Allows make sure that the loop is really necessary before using it. Solidity has implemented: for loops, while loops and do... while loops.
Function overloading
In Solidity function overloading is supported. To overload a function, our contract must have multiple function definitions for the same function identifier and within the same scope. The function definitions must differ from each other by the data types accept and/or the number of arguments accepted into the function. The example below demonstrates the overloading of the function sum() it is defined to accept 2 or 3 arguments.
// SPDX-License-Identifier: MITpragma solidity ^0.8.7;
// function overloading examplecontract FunctionOverlading {
// function sum accepting 2 argumentsfunction sum(uint a, uint b) public pure returns (uint) {
return a + b;
}
// function sum accepting 3 argumentsfunction sum(uint a, uint b, uint c) public pure returns (uint) {
return a + b + c;
}
uintpublic sumOf2 = sum(1, 2);
uintpublic sumOf3 = sum(1, 2, 3);
}
Conversion: implicit and explicit
Types can be converted to other types in Solidity. There are two kind of conversion: explicit conversions and implicit conversion. If the compiler doesn't allow implicit conversion it can still be done using the explicit type conversion. But this comes with risk and can result in unexpected behaviour. In essence it allows to bypass some security features of the compiler, so use it very carefully. In the example below we convert a uint256 data type to a bytes32 data type by using explicit conversion.
uint a = 123456;
bytes32 b = bytes32(a);
Ether units
In Solidity we can use different denominations of Ether: wei, gwei and ether as suffixes. The wei is the smallest unit in Ethereum and used to measure the gas cost of a contract. In Solidity version 0.7.0 the denominations finney and szabo have been removed. To convert Ethereum units use our wei converter.
// ether unit denominations in Solidityassert(1 wei == 1);
assert(1 gwei == 1e9);
assert(1 ether == 1e18);
Time units
Similar to the use of Ether denominations we can also use suffixes for time units: seconds, minutes, hours, days and weeks. The units are implemented naively and it's the developers responsibility to account for leap years and leap seconds in the logic of the smart contract. The suffix years was removed in Solidity version 0.5.0.
// time units in Solidityassert(1 == 1 seconds);
assert(1 minutes == 60 seconds);
assert(1 hours == 60 minutes);
assert(1 days == 24 hours);
assert(1 weeks == 7 days);
Examples
The following examples are simple contracts written in Solidity to demonstrate the functionality of the Solidity programming language.
counter
Learn more about Modifiers in Solidity.