Introduction
While most people have heard about blockchain development and the brief concept about decentralisation, the barrier to entry as a blockchain developer has been what most people battle with, making it quite difficult to start with. This article will guide you through the necessary steps to take in becoming a blockchain developer building on Celo blockchain.
Prerequisites
-
It is assume you are an absolute beginner
-
Before you proceed with this article, It’s assume you have a basic knowledge of what blockchain development entails.
-
Having some web2 knowledge is a plus to getting started with this article.
Requirements
- Remix IDE will be use in this tutorial
Getting Started
Starting with Celo blockchain, Celo blockchain is a carbon-negative, EVM compatible blockchain targeted at mobile users. Celo’s EVM compatibility means that any smart contract written for Ethereum blockchain can easily be deployed to Celo. With this compatibility, the languages used on Ethereum can also be used on Celo blockchain, which will drive us to exploring and understanding Solidity (The most popular language on Ethereum).
The aim of this article is to break the necessary barrier to entry on getting started with blockchain development. It’s common to see tutorials explaining different concept about building on Celo blockchain but in most cases, beginners usually have some hard time on which article to go with, and in the case of documentation, most of the time, it seems too bulky for newbies, hence, the reason for this article. This article will link beginners to the necessary tutorial to start with while explaining some basic concept, which in return will grow their confidence in reverting back to the Celo official documentation. At the end of this tutorial, we will write a simple todo contract to ground our understanding on the basics of solidity.
Celo Architecture
Before building on Celo blockchain, it’s important to understand the stack that makes up Celo as a whole. Celo stack is sectioned into three part:
- Celo blockchain
- Celo Core Contract
- Celo Applications
Starting with the Celo blockchain, it’s an open cryptographic protocol that allows application make transactions and let smart contract run in a secure and decentralized manner. Sharing some similar features with Ethereum, it uses a Proof-Of-Stake consensus mechanism.
Celo Core Contract are set of smart contract running on the Celo blockchain, they are part of what makes up the protocol. They are upgradeable and managed by the decentralized governance process.
Celo Applications are for end users to build on the Celo platform. Before a user can start building on the Celo Platform, it’s important you have some necessary setup already in place, e.g: code editor (VS Code), EVM compatible wallet like metamask or Celo wallet.
Check Here to know more about Celo Architecture.
Building on Celo
In our previous section we talked about Celo Application as part of Celo architecture for end users to build smart contracts and decentralized application on Celo Platform. Before you can build on Celo platform, knowledge on EVM compatible language is required. For this article, we will give an overview on the basics of Solidity.
Solidity is an object oriented, high level and statically typed language for implementing smart contract. Smart contract are self-executing program based on conditioned logic. Here is an example of “Hello World” Solidity smart contract that you can copy and paste in your remix IDE, create a file in your remix IDE and paste the code below.
// SPDX-License-Identifier: MIT
pragma solidity 0.8.18;
contract HelloWorld {
string public greet = "Hello World!";
}
You have successfully created your first solidity smart contract program . Before we proceed i want you to take note of comment in solidity. Comment in solidity can be declared with “//” and “/* * /”. Any text after a // is treated as a comment, and any text between the characters /* and */ is treated as a comment. This declarations are ignored by the solidity compile. It is used for explaining your code.
Programs written on Celo and other blockchains are referred to as “contract”, so i will be using the word contract till the end of this tutorial.
Solidity Breakdown
Solidity as mentioned above is a statically typed language, which means variable types are explicitly declared and are determined at compile time, unlike dynamically typed language that perform type checking at runtime. As most people learn by example, looking at our HelloWord contract above, the variable greet is assigned to a string data type, which ensures greet accept string values only. In that case
changing “Hello World!” to 34 will throw a TypeError
// SPDX-License-Identifier: MIT
pragma solidity 0.8.18;
contract HelloWorld {
string public greet = 34; // This will throw a TypeError stating Type int_const 34 is not implicitly convertible to expected type string
}
The error above state that it is impossible to assign an integer to a string variable.
Solidity Data Types
It’s important to know the types available in solidity in other to know which to declare for a specific variable use case. This section will guide us through all the solidity data types with a proper example on grasping how the type can be incorporated into our contract. The solidity data types we have are:
Boolean: This is a data type used to declare variables that accept true or false, with logical operators ! (not), && (and), || (or), == (equal), and != (not equal) as a value.
// SPDX-License-Identifier: MIT
pragma solidity 0.8.18;
contract BoolPractice {
bool greeted = true;
}
This code above assigned true to variable greeted. As you can see, this is different from what we have with string data type in our previous section, you may be worried about “public” (function visibility) not being used here, it has nothing to do with the declaration and we will discuss about it later in this tutorial.
Integer(int,uint): Integer data type is sectioned into a “signed integer” and “unsigned integer” . Signed integer (int) can be declared using int8 up to int256 with an increment of 8 bits, that is, int8, int16, int24, int32…up to int256. You can choose which to use based on the value you want to store. Here is an example showing each declaration with their capacity.
// SPDX-License-Identifier: MIT
pragma solidity 0.8.18;
contract IntegerPractice {
int8 storeInt8 = -24; // This can take integers from -2^(8-1) to 2^(8-1)-1. that is, integer from -128 to 127
int16 storeInt16 = 2000; // This can take integers from -2^(16-1) to 2^(16-1)-1. that is, integers from -32768 to 32767
}
This go on up to int256.
Also for unsigned integers(uint). uint doesn’t take any negative integers, meaning, it takes value only from zero to its max declaration. Here is an example showing each declaration with their capacity.
// SPDX-License-Identifier: MIT
pragma solidity 0.8.18;
contract IntegerPractice {
uint8 storeUint8 = 70; // This can take integers from 0 to (2^8)-1, that is, 0 to 255.
uint16 storeUint16 = 5000; // This can take integers from 0 to (2^16)-1, that is, 0 to 65535.
}
and this go on up to uint256, taking integers from 0 to (2^256)-1.
Address: This data type is used to declare variables that accept only Celo addresses as value.
Enum: enum is a user defined type for enumerating discrete values, quite similar to typescript Enum, for those familiar with it. You can see it as an alternative to using boolean extensively. For example:
// SPDX-License-Identifier: MIT
pragma solidity 0.8.18;
contract EnumPractice {
// In a situation where we need to select from many options beyond boolean true or false
// we can create an enum to address this instead of creating extensive list of booleans.
// Say, we want to select from either "success, pending, reject" option.
// Doing this with a boolean, can be computationally expensive, instead we can settle to create it with enum.
// enum declaration
enum Status {
success,
pending,
reject
}
// We can go on to use our declaration
Status myStatus = Status.pending;
}
With the example above, after we have declared our enum, the enum declaration is now seen as a user defined type, that is, using “Status” as a type. The same pattern is applied for struct.
Struct: While enum is used for enumerating discrete values, struct is a user-defined type for grouping different variables. For example:
// SPDX-License-Identifier: MIT
pragma solidity 0.8.18;
contract StructPractice {
// struct declaration
struct UserDetails {
string name;
uint256 age;
string place;
}
// we use our declaration
UserDetails myDetails = UserDetails("kayzee", 9, "Metaverse");
}
We will definitely incorporate most of this solidity data types into our voting contract practice by the end of this tutorial for better understanding, so don’t worry too much .
Mapping: mapping is a solidity data type that stores data as key-value pairs, where the key can be any of the built in data types, excluding reference data types (Reference and Value data types are explained here).
You can take mapping as a “car key” to the “car” itself. With the car key, you can access the car and do other things with it. (I think this is the simplest example of how mapping works, it’s not worth overthinking though )
string: string is a data type to declare variables of type string. Remember how our “Hello World!” is being declared.
Bytes Array (Fixed, Dynamic): Fixed size bytes of array can be declared with bytes1 upto bytes32. bytes(n) means it can only take in n bytes of value, that is, bytes1 can only take in 1 bytes of value and so on. Dynamic bytes array on the other hand can take in any bytes value without limitation due to its type. This will take us to understanding Reference and Value types.
Solidity Reference and Value Types
In Solidity, data types can either be value type or reference type. Starting with definition, Value type variables stores their own data, some of which are Boolean, Integer, Address, enums, reference type on the other hand store location of the data (i.e, they make reference to the data’s memory or storage location), they are responsible for complicated data structure, example of which are Arrays, mapping, struct, strings. Understanding reference and value type will help you know which one to use when the need arise. Using reference type within a local variable (i.e, within a function) must be added with pointer.
Visibility
While this is basic, it is important we round it up with visibility in other not to get confused when we start working on our smart contract.
In solidity, we can control who has access to the functions and state variables in your contract and how they interact with them, this concept is known as Visibility.
A functions visibility can be set to either external, public, internal or private, while state variables (variables declared outside of a function) only have public, internal or private, the keyword external is not applicable to state variables. State variables are internal by default.
External Visibility: When used in a function, the function can only be called from outside the contract in which they are declared.
Public Visibility: Functions and state variables declared with public visibility can be accessible within and outside the contract. When visibility is not specified for functions, the default visibility is public.
Internal Visibility: Internal functions and variables are only accessible within the contract in which they are declared, although they can be accessed from derived contract. Reference to contract inheritance will be made at the end of this tutorial.
Private Visibility Functions declared with private keywords are only accessible within the contract in which they are declared.
Code Practice
After walking through the theoretical approach, it is important we work on some practice to put our learning into use. Our contract will be as basics as possible for better understanding on everything we have discussed.
We will be using Remix IDE for the code practice. Remix IDE is an online IDE for developing, deploying, debugging and testing EVM-Compatible smart contracts.
Here’s a link to remix - https://remix.ethereum.org/
You should have something like this below
We will be working on a simple todo smart contract, a smart contract where people can create, read, update and delete their todo list. Right click on the contract folder in Remix IDE and create a todo.sol file, follow with the code below and practice.
// SPDX-License-Identifier: MIT
pragma solidity 0.8.18; // solidity compiler version we are using
// This is the starting point of our todo contract
contract Todo {
// Mapping is used to align todo creators to their todo lists.
mapping(address => string[]) _todoDetails;
// While explaining i mentioned about using a pointer along with refernce data type declaration in local variable
// Example of it is what we have in our addTodo parameter declaration.
function addTodo(string memory _todo) public {
_todoDetails[msg.sender].push(_todo); // msg.sender is a global variable. It is the address that initiate the function call (user address)
}
// This function can be used to update the todo by stating the index number of the todo you want to modify
function updateTodo(uint256 index, string memory _todo) public {
_todoDetails[msg.sender][index] = _todo;
// mapping can be accessed by: variablename[keyType]. this will give you access the value
// justas how we used it above.
}
// This function gives us accessiblity to view our todo created.
// External visibility is used here, since we are only calling it outside the contract.
function checkTodo() external view returns(string[] memory){
return _todoDetails[msg.sender];
}
// This will help user delete their todo when needed.
function deleteTodo() public {
uint256 getLength = _todoDetails[msg.sender].length;
for(uint256 i = 0; i < getLength; i++){
_todoDetails[msg.sender].pop();
}
}
}
Even though, the implementation is basic, it can be logical to newbies, understanding the code above will open you to different implementations combined with the practices we explained when talking about data types.
Additional Guide
Check through this link below for additional knowledge about Celo and solidity. Following the link step by step, will boost your journey to become a professional blockchain developer building on Celo blockchain.
Go through this tutorial to understand the basics of Solidity
Solidity smart contract developer pathway
Conclusion
This article is created to be brief and help an absolute beginner break the necessary barrier to entry on getting started with developing on Celo. It is advisable you check up on the external link provided in this article, any possible problem encounter can be addressed
Next Steps
After going through this article, i believe you would have gain the necessary confidence on proceeding with other Celo related article, i advice you to proceed with familiarizing yourself with the official celo documentation and some intermediate tutorials on celo academy.
About the Author
Kazeem Olaniyi
Kazeem is a Blockchain developer that works on both Frontend and Smart Contract development, he’s keen on solving any blockchain related problem that comes is way, which has lead to him having numerous number of contribution to different organisations. Connect with me on LinkedIn: Kazeem Olaniyi