Learning Solidity: Part Two
Tags: solidity, ethereum, blockchain
Published: 2018-04-26 21:52:18

---
title: Learning Solidity: Part Two
published: true
description: We go deeper this time!!
tags: solidity, ethereum, blockchain
cover_image: https://thepracticaldev.s3.amazonaws.com/i/1dp3eumrjmvl9nb528vg.png
---

### Introduction

In my last article, we got started with Solidity by creating a simple contract and exploring some simple structures and concepts. We will pick up where we left off.

## Mappings


After *struct* and *arrays*, we can also store data in *mappings*. Mappings are a key-value store. For example:

```
mapping(uint => string) public keyUintStringValue;
mapping(address => uint) public addressToUint;

```

Here, we have two public mappings. The first one has a *uint* key and a *string* value. The second has an *address* key and a *uint* value.

#### Addresses

The Ethereum blockchain is made up of addresses. Each account has an unique address. It takes the following form: `0x0cE440255306E921F41612C46F1v6df9Cc969183`. Each address has a certain amount of *Ether*, which is the cryptocurrency used on the blockchain, and can receive or send Ether to other addresses.

With that in mind, let's create a new mapping for our DeveloperFactory:

```
pragma solidity ^0.4.22;

contract DeveloperFactory {

    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;

    mapping (address => uint) public ownerDevCount;
    mapping (uint => address) public devToOwner;

    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 );
    }
}
```

In the first mapping, we will keep track of the number of devs each account ( address ) created. In the second, we will keep track of the owners for each dev.

### msg.sender

Each contract is passive, they don't do anything until someone triggers them. *msg.sender* is a global variable that allows us to know which address is responsible for the triggering. It could be a account or another smart contract.

With that information, we can update our mappings appropriately. In the *_createDeveloper* function, we will increase the *ownerDevCount* for this particular address. In the *devToOwner* mapping, we will indicate that the newly created developer is owned by the *msg.sender* address.


```
pragma solidity ^0.4.22;

contract DeveloperFactory {

    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;

    mapping (address => uint) public ownerDevCount;
    mapping (uint => address) public devToOwner;

    function _createDeveloper( string _name, uint _id, uint _age ) private{
        uint id = developers.push( Developer( _name, _id, _age ) ) - 1;
        ownerDevCount[msg.sender]++;
        devToOwner[id] = msg.sender;
        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 );
    }
}
```

Notice the *++* notation to increase the *ownerDevCount[msg.sender]*, just live Javascript!

### Inheritance and import

Contracts can inherit from other contracts. If you open a new file call *DeveloperLearning.sol*, you can make it inherit from *DeveloperFactory.sol*:

```
pragma solidity ^0.4.22;

import "./DeveloperFactory.sol";

contract DeveloperLearning is DeveloperFactory {
    // I have now access to DeveloperFactory functions
}
```

Notice how we imported the *DeveloperFactory* contract ( assuming it was in the same folder ). To declare inheritance, we use the keyword *is*.


### payable 

In order for a contract to receive *ether*, we need to have the *payable* keyword to a function. The amount sent will be accessible in the global variable *msg.value*. So we could make sure that a certain amount of ether is sent to the contract before the creation of a developer:


```
pragma solidity ^0.4.22;

contract DeveloperFactory {

    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;

    mapping (address => uint) public ownerDevCount;
    mapping (uint => address) public devToOwner;

    function _createDeveloper( string _name, uint _id, uint _age ) private{
        uint id = developers.push( Developer( _name, _id, _age ) ) - 1;
        ownerDevCount[msg.sender]++;
        devToOwner[id] = msg.sender;
        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 payable {
        require(_age > minAge);
        require(_age < maxAge);
        require(msg.value == 5);
        uint randId = _generateRandomId( _name );
        _createDeveloper(_name, randId, _age );
    }
}

```

### Memory and Storage

In Solidity, there are two places where variables are stored: in storage or in memory. A variable stored in memory is temporary, it exists while the function is used, then it is discarded. A variable stored in storage exists permanently on the blockchain. Most of the time, you don't have to worry about where to store your variables, as Solidity handles it for you.

For example, state variables ( maxAge, minAge, Developer ), declared outside of functions, are stored in storage. Variables like randId, id, rand are stored in memory.

But, in some cases, you want to explicitly declare where to store certain variables. Solidity allows you to do that with `memory` and `storage` keywords.