Writing your first Solidity Smart Contract for Ethereum

Author: Shane Larson

In this article we will write our first solidity smart contract and compile it with the SOLC-JS compiler.

In this article, we'll be creating our first smart contract for Ethereum using Solidity. The program itself is quite simple, and doesn't do very much except store a contract-level variable, and output the contents of the variable. However, it will provide a good starting point for more complex contracts.

At this point you should already have your development environment set up, including having a text editor like Visual Studio Code, Node.js and the SOLC-JS compiler. If not, you can take a look at setting up your crypto development environment.

We will explore the code today, and look at how the application compiles. In the next article we will explore a way to deploy our smart contract to a local blockchain called Ganache.

Writing the Code

The source code for this article can be found in my public git repo. The code is open-source licensed under the GNU Public License and you can use the code as you wish for personal or commercial use. Source Code

The smart contract that we're going to write is going to be called helloworld.sol. In your development ide. you can create the file by clicking the "New File" icon in the Visual Studio Code IDE. Feel free to name the file what you want as long as the file extension is .sol (solidity file extension).

Adding a new file in Visual Studio Code

The first line in the program is in the form of a solidity comment. It's not required for your application to compile, but the absence of this line will cause the compiler to throw errors. This line is for the SPDX Identifier, which makes clear the Open Source license for the contract.

// SPDX-License-Identifier: GPL-3.0

After the SPDX Identifier comment comes the pragma statement. A pragma statement is a directive that specifies the compiler something that the Solidity compiler should know during compile time.

This particular pragma statement is called the version pragma. It tells the compiler to reject compilation with future compiler versions that might introduce compatibility problems. As of this writing, my SOLC compiler is at version 0.8.12. So I chose this most current version for this statement. It's worth noting that there are actually other pragma statements which can be added to a Solidity application which you man encounter later in your journey.

pragma solidity ^0.8.12;

If you have ever written programs in c-like languages or JavaScript, you will find the syntax to be somewhat similar in Solidity. Solidity was modeled off of JavaScript because it was thought that it would encourage mass adoption of the language, which was a good move since so many developers have written code in that language at least once in their careers.

The contract in Solidity is very much like a class in object-oriented languages. Contracts can contain state variables, functions, events, errors and other much more. Contracts can also extend other contracts, which provides the ability to inherit contract properties and functions.

contract HelloWorld{


In this contract, the requirements are to store a message that is decided upon when the contract is deployed. And to provide a function that allows someone to retrieve that message. So the contract will need to next have a variable declaration in place so that this message can be stored. This data is called a state variable, because it keeps track of the state of the contract.

The message is technically a string in most programming languages. In this case we are going to choose bytes32, so as to limit the size of the string buffer. Space on a blockchain comes at a price, because it costs gas to store data on the chain when you deploy the contract.

So the next line of code is simply a state variable declaration, where we name a bytes32 variable called message.

bytes32 message;

Next, we will create the constructor method that is called when the Solidity smart contract is deployed successfully to the network. The program requires that the message be able to be set at the time the program is run, so we will pass in an argument to the constructor message for the message, that is in the same data type as the message variable. We will then set the contract's message state variable to the message that was passed to the constructor.

constructor(bytes32 myMessage){
    message = myMessage;

And finally, there is the function to get the message state that is stored in the contract. There are a few keywords used in this function that need to be explained. The first portion of the function definition are fairly straightforward. But next there are three details about the function that need to be explained.

The public access modifier is next used. This modifier tells the compiler that this function is publicly executable on the blockchain. This is needed here so that someone who wants to can create a transaction to call this function, which would return the message.

Next, the view modifier is used, which tells the compiler that this function is a view function and that it promises to not make an alteration to the smart contract'a state.

Finally, the function returns the message as the bytes32 data type.

function getMessage() public view returns(bytes32) {
    return message;

We have finally gotten to the point there or first smart contract has been created. Below is the entire smart contract's source code,with comments.

// SPDX-License-Identifier: GPL-3.0
// pragma statement - indicates which version of the solidity compiler to use.
pragma solidity ^0.8.12;

// Create a contract called HelloWorld

contract HelloWorld{

// data type bytpes32 is typically used for string,
// string type is also available but bytes32 reserves less space.
// blockchain storage is expensive, so we keep the contracts as lean as possible.
bytes32 message;

// construtor method
// runs once, when the contract is created (deployed to the blockchain)
// used to initialize contract state variables.
constructor(bytes32 myMessage){

    // set default message to the value passed to the constructor
    message = myMessage;

    // create a function on the smart contract that returns the message
    // publicly executable method
    // using the 'view' modifier tells the compiler that this function does not save state 
    function getMessage() public view returns(bytes32) {
    return message;

Next we will want to compile the source code using the SOLC compiler. So in order to do this go the the CLI or terminal and navigate to the folder where the solidity program is stored and type the following command to invoke the compiler.
solcjs helloworld.sol --bin

As long as no errors occur the compiler should eventually return control to the cursor, and a file named helloworldsolhelloworld.bin should be found in the folder. This file will contain the bytecode for the smart contract! EVM bytecode can be deployed to an EVM-compatible blockchain. Below is an example of this application's bytecode.


And that's it! We have successfully written our first smart contract and compiled it. But that this point, it really doesn't do anything does it? That's because the smart contract is not yet deployed to a blockchain. We need to fix that!

In the next section we are going to learn about Ganache. This is a Ethereum development tool that allows the developer to run a local blockchain server right on their development machine with just a few clicks. And after that we will learn about using truffle to deploy a contract to the blockchain that we set up with Ganache.

Recent Articles

Shane Larson

Software Engineer - Solutions Architect

Builder of Tiny Cabins in Alaska

I'm a software engineer with years of professional experience in NodeJS, Solidity, React, C#, Python, JavaScript, Postgres, SQL Server, MongoDb.

My current focus is in the areas of Microservices, API Frameworks, Cloud Native Architecture, Robotics, and DevOps.

I work as a Solutions Architect in the financial industry.

I also build tiny cabins in Alaska.

Author of Building Microservices with NodeJs

Packt Publishing

Microservices enable us to develop software in small pieces that work together but can be developed separately, one of the reasons why enterprises have started embracing them. For the past few years, Node.js has emerged as a strong candidate for developing these microservices because of its ability to increase developers' productivity and applications performance. This video is an end-to-end course on how to dismantle your monolith applications and embrace the microservice architecture.

Powered by Contentful