Mapping

Your SpaceMuffin contract looks gorgeous. It has levels and address of its fans. But how would you check if someone is a fan? You could check each index but that wouldn't be very efficient. Otherwise, you can turn to mappings. They act as a table but indexed by whatever type you like.

What is it

A mapping is like a table but the index can be any built-in type. So you can have arrays mapping address to Fan. In SpaceMuffin, it would be very convenient to have such a mapping. We would just need to modify the Fan structure to include the level and id of the user.

Use

Declaration

To declare a mapping, just procede as in the example below

// `mapping` is a keyword, then you have (builtin_type => value_type)
mapping(address => uint) public ledger;

Exercise
Correct!
False!

Loading...

Change fans to be a mapping of address to Fan
pragma solidity ^0.4.24; contract SpaceMuffin { enum Levels { Fan, Excited, InLove, CrazyInLove } struct Fan { Levels level; uint id; // now there is an id } // replace the definition of fans Fan[] public fans; }

Hint

  • Notice struct Fan has changed

Access

Accessing a map is simple. It works the same way as accessing array, except the index is not necessary a uint. It is called a key.

mapping(address => uint) private ledger;

function access(address key) view public returns (uint) {
  return ledger[key];
}

function add(address key, uint value) public {
  ledger[key] = value;
}

Exercise
Correct!
False!

Loading...

Update like function to match the new definition of fans. For the id, declare lastId = 0 and insert lastId + 1. Then increment lastId
pragma solidity ^0.4.24; contract SpaceMuffin { enum Levels { Fan, Excited, InLove, CrazyInLove } struct Fan { Levels level; uint id; } mapping(address => Fan) public fans; // declare `lastId` here modifier notMaxLevel(Levels level) { require(level != Levels.CrazyInLove); _; } // this function is not written properly anymore function like() public { fans.push(Fan({contact: msg.sender, level: Levels.Fan})); } // looks like this function has been updated function update() public notMaxLevel(fans[msg.sender].level) { fans[msg.sender].level = Levels(uint(fans[msg.sender].level) + 1); } }

Hint

  • Declare lastId with a visibility
  • The definition of Fan has changed, take a look at it
  • The new fan is the one that calls the function

Check presence

Checking if an element is in an array is done by getting the length of the array and checking the given index is strictly lower than this length. In a mapping, there is no such property. There are two possibilities to check if an element has been allocated

First way is to maintain an array of the keys that were added. It is deterministic but costly.

struct BetterMapping {
  mapping(address => uint) ledger;
  address[] keys;
}

Second way is to check if the value associated to a given key is a default value. You are therefore forbidden to use this value later on.

mapping(address => uint) internal ledger;
// for all keys, ledger[key] == 0 because 0 is the default value for a uint
// we cannot use 0

Exercise
Correct!
False!

Loading...

update function calls hasFan modifier. hasFan checks if msg.sender is a fan
pragma solidity ^0.4.24; contract SpaceMuffin { enum Levels { Fan, Excited, InLove, CrazyInLove } struct Fan { Levels level; uint id; } mapping(address => Fan) public fans; uint internal lastId = 0; // declare hasFan modifier here modifier notMaxLevel(Levels level) { require(level != Levels.CrazyInLove); _; } function like() public { fans[msg.sender] = Fan({level: Levels.Fan, id: lastId + 1}); lastId += 1; } // Nothing to change here, I've updated it for u <3 function update() public hasFan(msg.sender) notMaxLevel(fans[msg.sender].level) { fans[msg.sender].level = Levels(uint(fans[msg.sender].level) + 1); } }

Hint

  • Check update to see the arguments of your modifier
  • What is the default value for a Fan?
  • In Fan's default value, take a look at id and if it is ever used (help: it is never used)

Return

As for structures, Solidity doesn't support return of mappings for public and external function.x

results matching ""

    No results matching ""