7 Important Concepts About Solidity Programming

As part of learning more about programming applications for the blockchain, I have been using Solidity to build sample contracts on the Ethereum blockchain. In the process, I've discovered a number of interesting aspects of this programming language that would be of interest to any beginner. In this post, I'll explain 7 of them. 

1. Solidity is a statically typed language, meaning variables must be defined by their type. This is necessary both when instantiating variables in the beginning of a contract and when passing variables through to functions as arguments. 

2. Functions can be defined with a number of different special words which determine their access level and what they are responsible for: 

  • Public = can be called from outside the current contract. 
  • Private = must be called from inside the current contract. 
  • View = doesn't modify the application state, just reads some data.
  • Pure = the return value is only dependent on data passed as arguments. This function doesn't need to read from the application state. 
  • Internal = accessible in other contracts that inherit from the contract in which it is called.
  • External = only callable from outside the codebase. 

For example, an externally available function that only reads data could be instantiated as follows: 

function getUserId (string _name) public view {
    // function code goes here
}

3. Holding on to variables can happen in two distinct ways, which must be declared explicitly. 

  • Storage = variables stored permanently.
  • Memory = temporary variables that don’t get stored on the blockchain. 

One important detail to understand about storing data is that if you declare a struct or array within a function, you must also declare explicitly if that variable should be saved in storage or in memory. You can do this like so: 

User storage myUser = user[_userId];

Here we instantiate a user of the type User named myUser based on the _userId, storing the information in an array that will be stored permanently in the blockchain database.  

4. Solidity doesn't have direct comparison. Instead if you want to compare the equality of two strings, you will have to hash them first using the built-in keccak256 hashing mechanism. For example: 

(keccak256(_name) == keccak256("Matt"))

5. It's often helpful to know where a request is coming from when dealing with blockchain applications. To aid with this, Solidity provides developers with msg.sender. Msg.sender is a global variable for all external function calls that allows you to determine who is making the call to your contract’s code.  

6. Solidity has an interesting functionality called mappings. A mapping is a key-value store that enables you to access  or update information from the value based on the key that is being passed through. These named mappings can be useful for setting and retrieving data about a certain user. For example: 

mapping (uint => address) public postToOwner;
postToOwner[id] = msg.sender;

In this example, we are able to set a post's owner by passing through the id of the post, then setting the owner address to msg.sender. 

7. As a form of validation, it can be helpful to start function calls with the "require" keyword. This enables developers to ensure certain consistencies are met before executing a block of code. Here, we can combine the usage of a mapping and require to make sure that the person sending the request is the same as the post owner before executing the "deletePost" function. 

function deletePost(uint _id) public {
    require(msg.sender == postToOwner[_id]);
    // delete post
}

That's all for now. Any questions or corrections? Let me know in the comments below!