Create your account

Already have an account? Login here

Note: By joining, you will receive periodic emails from Coursetro. You can unsubscribe from these emails.

Create account

Solidity Mappings & Structs Tutorial

By Gary simon - Oct 30, 2017

The following tutorial is a part of our 100% free course: Developing Ethereum Smart Contracts for Beginners

If you have been following along with the free course from which this tutorial is just another piece, then you know we've been working on a smart contract called Coursetro

It's quite simple, it allows you to set an instructor's name and age. We can also interact with this smart contract through a web3 UI.

To demonstrate the next 2 topics in the course, which are Mappings and Structs, we're going to restructure our smart contract to allow for adding multiple instructors, along with retrieving the data associated with them based on their account as a key.

Let's get started..

If you prefer watching a video instead..

Be sure to Subscribe to the Official Coursetro Youtube Channel for more videos.

Creating a Struct

A struct in solidity is just a custom type that you can define. You define the struct with a name and associated properties inside of it.

Start a new file in the Remix IDE called Courses.sol and paste the following:

pragma solidity ^0.4.18;

contract Courses {
    
    struct Instructor {
        uint age;
        string fName;
        string lName;
    }
}

Here, we have a struct of Instructor, which will store their name, first name and last name.

It would also be handy if we could reference each instructor by their Ethereum address. That's where we'll create a mapping.

Creating the Mapping

In Solidity, a mapping is referred to a hash table, which consists of key types and value type pairs. We define a mapping like any other variable type:

contract Courses {
    
    struct Instructor {
        uint age;
        string fName;
        string lName;
    }
    
    mapping (address => Instructor) instructors;
    address[] public instructorAccts;

}

Here, we're creating a mapping, which accepts first the key type (in our case, it will be an address type), and the value type will be our Struct that we created above, then we're referring to this mapping as instructors.

This will allow us to look up a specific instructor with their Ethereum address, and retrieve their age, first name and last name.

The line beneath it is to define an address array that will store all of the instructor addresses. This is useful because you currently cannot return a mapping like instructors and simply iterate through all of the available instructors. Instead, you would have to return a list of instructor accounts with instructorAccts and then make a specific function call to grab the Instructor's information based on the Ethereum address.

Adding to a Mapping

Being that our smart contract structure is now significantly different from the previous contract, let's examine what it takes to add a instructor to this new format:

    // Previous code removed for brevity
    
    function setInstructor(address _address, uint _age, string _fName, string _lName) public {
        var instructor = instructors[_address];

        instructor.age = _age;
        instructor.fName = _fName;
        instructor.lName = _lName;
        
        instructorAccts.push(_address) -1;

    }

In the arguments, we're passing an address, age, first name and last name; simple enough.

Next, we're creating a variable instructor and binding it to the instructors mapping and passing in the _address as the key.

We then set the age, first and last name.

At the end, we push the new instructor address to the array of addresses instructorAccts.

Getting from a Mapping

We can now add new instructors to our mapping, but what if we wanted to retrieve them? Well, first we'll create a function that returns a list of addresses from instructorAccts:

    // Other code removed for brevity

    function getInstructors() view public returns (address[]) {
        return instructorAccts;
    }

Great. Now that we have access to specific accounts, we can create another function beneath it that will retrieve a specific instructor based on a provided address:

    function getInstructors() view public returns (address[]) {
        return instructorAccts;
    }

    function getInstructor(address ins) view public returns (uint, string, string) {
        return (instructors[ins].age, instructors[ins].fName, instructors[ins].lName);
    }

Awesome. Create the contract, copy the account address with the account used to create the contract, and enter this into setInstructor: "ethaddress", 34, "Gary", "Simon"  and click the setInstructor button.

Then, click on the getInstructors button. This will provide you with the address you entered.  Copy it, and then paste it with quotes surrounding it into the getInstructor textfield, and click the button.  

It should return you with the age, first name and last name of the provided account.

Go ahead and add another instructor with a different account from the list of accounts above and try it out!

Counting from a Mapping

It would be nice to know how many instructors we have, so let's create a function for that:

    function getInstructors() view public returns (address[]) {
        return instructorAccts;
    }

    function getInstructor(address ins) view public returns (uint, string, string) {
        return (instructors[ins].age, instructors[ins].fName, instructors[ins].lName);
    }

    function countInstructors() view public returns (uint) {
        return instructorAccts.length;
    }

Re-create the contract, add a new instructor and click countInstructors, simple enough!

The Full Contract

Here is the full contract so far:

pragma solidity ^0.4.18;

contract Courses {
    
    struct Instructor {
        uint age;
        string fName;
        string lName;
    }
    
    mapping (address => Instructor) instructors;
    address[] public instructorAccts;
    
    function setInstructor(address _address, uint _age, string _fName, string _lName) public {
        var instructor = instructors[_address];
        
        instructor.age = _age;
        instructor.fName = _fName;
        instructor.lName = _lName;
        
        instructorAccts.push(_address) -1;
    }
    
    function getInstructors() view public returns(address[]) {
        return instructorAccts;
    }
    
    function getInstructor(address _address) view public returns (uint, string, string) {
        return (instructors[_address].age, instructors[_address].fName, instructors[_address].lName);
    }
    
    function countInstructors() view public returns (uint) {
        return instructorAccts.length;
    }
    
}

Conclusion

Being that our smart contract has been completely revamped, our UI will no longer work. Don't worry, we're going to come back to it and make it work with this new contract.

But first, we're going to learn how you can make payments to other accounts.


Share this post




Say something about this awesome post!