Introduction
Solidity is a high-level language used to implement smart contracts. This is an object oriented language designed to target the Ethereum Virtual Machine. Let's explore it!
Let's go!!!
Let's create a file called Contract.sol
First, you must define the version you are using. This is an information the compiler needs.
pragma solidity ^0.4.22;
All code in Ethereum belongs to a Contract. Let's create a contract and define a few variables inside it.
pragma solidity ^0.4.22;
contract DeveloperFactory {
// Let's create a Developer!
uint dnaDigits = 16;
uint ageDigits = 2;
}
Solidity is a typed language. uint stand for Unsigned Integer ( non negative integers ). These variables are state variables. They will be permanently stored in the contract storage ( in the Ethereum Blockchain ). Our Developer has a dna of 16 digits and an age of 2 digits.
Let's keep going!
Struct and arrays
pragma solidity ^0.4.22;
contract DeveloperFactory {
// Let's create a Developer!
uint dnaDigits = 16;
uint ageDigits = 2;
struct Developer {
string name;
uint dna;
uint age;
}
Developer[] public developers;
}
The struct variable allows us to define more complex data structures. Here the Developer struc takes a string called name, a uint called dna and a uint called age.
Solidity also has arrays. You can create dynamic or fixed arrays. Here, our Developer array is dynamic because we do not specify a length. So we can keep adding Developers to our army without any limitations.
Developer[5] public developers
is a fixed array that can contain 5 Developer struct.
Functions
A function would look something like this:
pragma solidity ^0.4.22;
contract DeveloperFactory {
// Let's create a Developer!
uint maxAge = 100;
uint minAge = 5;
struct Developer {
string name;
uint id;
uint age;
}
Developer[] public developers;
function _createDeveloper( string _name, uint _id, uint _age ) private{
developers.push( Developer( _name, _id, _age ) );
}
function _generateRandomId( string _str ) private pure returns (uint){
uint rand = uint(keccak256(_str));
return rand;
}
function createRandomDeveloper( string _name, uint _age ) public view {
require(_age > minAge);
require(_age < maxAge);
uint randId = _generateRandomId( _name );
_createDeveloper(_name, randId, _age );
}
}
We create functions with the function keyword. Functions can take parameters. By default, functions are public. I added the private keyword to make this function private. I also chose to add an underscore before a private function or variable to distinguish them from public variables. You don't have to do this, I just find it easier to read.
Ethereum has the hash function keccak256 built in. This is a version of SHA3. Pass it any string and you get a 256-bit hexadecimal number.
As you can see, we are typecasting the keccak256 value into a uint value and we return it.
Aside from the private keyword, there are several things you can add to a function:
The function returns something: Use the returns keyword and specify the type the function returns. Here, it will return a uint type.
The view keyword means that our function needs to look at some of our contract's variables, but not modify them. Our function createRandomDeveloper needs to look at minAge and maxAge variables.
The pure keyword means that the function is not accessing any data in the app. It only returns something depending on its parameters. Our _generateRandomId is pure.
We have three functions. _generateRandomId generates a random Id for our developer by using the keccak256 built in function. _createDeveloper creates and pushes a new Developer struct into our developers array. createRandomDeveloper is the only public function. It checks if the age provided is correct. The require statements will throw errors if it is not the case ( age greater than 100 and lower than 5 in our case ). So, this last function is the one that can be called from outside our contract.
Events
You can also create events so you can communicate what happens on the blockchain to your front-end app. Your app would then listen to those events and react accordingly.
pragma solidity ^0.4.22;
contract DeveloperFactory {
// Let's create a Developer!
event NewDeveloper(uint devId, string name, uint age);
uint maxAge = 100;
uint minAge = 5;
struct Developer {
string name;
uint id;
uint age;
}
Developer[] public developers;
function _createDeveloper( string _name, uint _id, uint _age ) private{
uint id = developers.push( Developer( _name, _id, _age ) ) - 1;
newDeveloper(id, _name, _age);
}
function _generateRandomId( string _str ) private pure returns (uint){
uint rand = uint(keccak256(_str));
return rand;
}
function createRandomDeveloper( string _name, uint _age ) public view {
require(_age > minAge);
require(_age < maxAge);
uint randId = _generateRandomId( _name );
_createDeveloper(_name, randId, _age );
}
}
We create an event with the event keyword. In our contract, the event will have three parameters, the devId, the name and the age. We will fire our event in our _createDeveloper function. It works like a function. The id is retrieved thanks to the push method on the developers array. It will return the new length of the array. Because the array start at index 0, we subtract 1 to get the developer id.
Note: This series is inspired by the CryptoZombies tutorial. Don't hesitate to check it out, it's amazing!
Note bis: You can use the Remix IDE in your browser if you want to play around in Solidity
Conclusion
We have explored some concepts of Solidity. In the next article, we will go in more depth into what Solidity allows you to do. Stay tuned!