Solidity Basics: Your First Smart Contract

Daniel Yamagata
6 min readJul 22, 2022

--

This is the prelude to a multipart series on Solidity

It seems like everyone has a Web3 project, but no one has a Web3 developer. Only 18,500 developers are active in Web3 — 0.07% of all developers globally! This extreme shortage isn’t driven by a lack of demand: smart contract developers earn an average base salary 50% higher than a typical software developer.

Solidity has become the defacto program language of Web3 developers and is used across crypto ecosystems. From the outside, it is seemingly impossible to learn, but it isn’t as complex as you might think. This series aims to demystify Solidity and take the reader from a beginner to an intermediate level of understanding.

Overview

Inspired by Javascript and C++, Solidity is a high-level curly-bracket, language used to create smart contracts compatible with the Ethereum Virtual Machine (EVM). Solidity code is broken down by a compiler, which subsequently outputs a binary file containing bytecode and an application-binary interface (ABI). An ABI is an interface file that tells other applications, libraries, and smart contracts how to interact with your code.

For a more in-depth, low-level understanding of the EVM, I suggest this video by the Ethereum Engineering Group

Gas and Computation

Layer-1 blockchains have a limit to their throughput in regards to computing power. To deter bad actors from overwhelming the network, computation on a blockchain is costly. Gas refers to the unit used to measure the cost of computing on a blockchain. Any action that changes the network state requires gas.

For more information, read the Ethereum docs

There are no floating numbers in Solidity. Instead, all values are denominated in Wei, the smallest subdenomination of ETH, Ethereum’s cryptocurrency. One ETH is equal to 10¹⁸ wei.

The reasoning behind this is simple: you shouldn’t use floating numbers to represent money. Therefore, the base unit of the language needs to be sufficiently small to accommodate for precise transfers of value.

Gas in Ethereum is denominated in gwei, which is 10⁹ wei or 0.000000001 ETH.

Frameworks and Libraries

There are a number of existing frameworks and libraries to interact with the EVM.

The Javascript frameworks Hardhat and Truffle are the most widely used for Solidity development and testing, while Brownie is a Python-based alternative. Recently, Paradigm developed and launched Foundry, which enables you to test your code with Solidity, itself.

If you plan to build a decentralized application, you will need to implement your frontend using either Ethers.js or Web3.js to interact with the EVM.

For this tutorial, we will be using Remix, a browser-based IDE.

Solidity Variable Types

Solidity is statically-typed, meaning that each variable needs to be specified when initialized.

Value Types

  • bool
  • int/uint
  • address // holds a 20-byte value of an Ethereum address
  • bytes
  • string

There exist keywords from int8 to int256 and uint8 to uint256 that specify the number of bits used.

Like C++ or Javascript, whitespace does not matter in Solidity. However, you must end each intended line using a semi-colon (;).

Visibility

Similar to access specifiers in other programming languages, functions and state variables in Solidity require a visibility modifier. There are four:

  • public: the function or variable can be called externally or internally by any other contract, account, or function. The Solidity compiler automatically generates getter functions for public variables at compile time
  • internal: the function or variable can only be accessed within the contract or by child contracts
  • private: private state variables and functions are similar to internal ones but cannot be accessed by derived contracts
  • external: only functions can be set to external. Functions marked external cannot be called internally by other functions

For more information, read this article or the Solidity docs

Functions can also be marked as view or pure.

  • view: the function cannot alter state variables. These functions are similar to const member functions in C++
  • pure: the function cannot access or modify state variables

All getter functions should be marked as view, while those that are used internally for math should be marked pure.

Your First Smart Contract

Below is Solidity’s “Hello World.”

// SPDX-License-Identifier: MITpragma solidity ^0.8.7;contract MyContract {uint256 myVar;
function setMyVar(uint256 newVal) public {myVar = newVal;}
function getMyVar() public view returns (uint256) {return myVar;}
} // end of myContract

To create a .sol file, click the button in the top-left below workspaces (see above). Name your file MyContract.sol

The first line of a .sol file should specify the SPDX license identifier. The Solidity compiler encourages this to avoid any legal problems stemming from the open-source nature of smart contracts. We will be using the MIT SPDX-License-Identifier.

// SPDX-License-Identifier: MIT

Next, we need to specify which version of Solidity we are using. This is accomplished by using the pragma keyword.

pragma solidity ^0.8.7;

You can explicitly specify the version of the Solidity compiler you want to use. By using ^, we are saying that the source file does not compile with any version earlier than 0.8.7

In Solidity, contracts act like a class and encapsulate state and implementations of behavior. To define a smart contract, use the contract keyword.

contract MyContract { … }

Next, we will initialize a uint256 and name it myVar.

uint256 myVar;

Solidity is a weird language: unless you are optimizing on space, it’s more cost-effective to use a uint256 rather than a uint8, uint16, etc.

If you want to learn why, read this article by Coinmonks

Functions are defined using the function keyword. Below, we define a public function to set a value to myVar.

function setMyVar(uint256 newVal) public {myVar = newVal;}

Since setMyVar changes state, a user must spend gas to execute the function. Don’t worry about this — we will be using Remix’s VM, which emulates a blockchain in your browser.

To get the value of myVar, simply call getMyVar( ):

function getMyVar() public view returns (uint256) {return myVar;}

When returning a value, you must specify the data type in the function declaration as well as the datatype of the returned value.

It is also important to remember that executing a function only costs gas if the function changes state. Querying data via a getter function does not cost gas.

Compiling, Deploying, and Interacting with MyContract in Remix

To compile the contract in Remix, hit ⌘S or Ctrl+S.

To deploy the contract, navigate to the Deploy and Run Transactions tab and click Deploy. Make sure the Environment is one of Remix’s VMs.

Next, navigate to the bottom left to interact with the deployed contract. Call setMyVar( ) with any whole number and then subsequently call getMyVar ( ):

Congrats! You just wrote and interacted with your first smart contract.

Be on the lookout for the next part in this series where I will teach you about reference types, how to deploy contracts from within a contract and how to interact with existing contracts.

Please reach out to me and my team at Bloccelerate VC if you are building in Web3. We are always looking to back great founders.

Website

LinkedIn

Twitter

Feel free to also drop me a note if you have any suggestions for any toolings or topics that I should cover in the future

--

--