Dynamic value arrays and sets compared with Solidity mappings
Smart Contract Implementation

We are effectively providing functionality in a base class. It is designed to be inherited in order to provide the desired functionality. This is actually hijacking inheritance as a substitute for object composition.

map/map

Here is a useful import file providing a base contract that provides the add and check functions:

contract BaseAccountRoles { // an account has many roles

mapping(address => mapping(uint => bool)) accountRoles;



function accountAddRole(address account, uint role) internal {

accountRoles[account][role] = true;

} function accountHasRole(address account, uint role) internal

view returns (bool) {

return accountRoles[account][role];

}

}

This contract uses Solidity’s excellent mapping feature to map from the given address to each given role, which in turn maps to a bool indicating whether the account address provides the role or not.

map/d31

Here is another useful import file providing a base contract that provides the add and check functions:

import "Bytes31fun.sol" contract BaseAccountRoles31 { // an account has many roles

using Bytes31fun for bytes32;



mapping(address => bytes32) accountRoles;



function addAccountRole(address account, uint role) internal {

accountRoles[account] = accountRoles[account].push(role);

} function confirmAccountRole(address account, uint role) internal

view returns (bool) {

return accountRoles[account].find(role);

}

}

This contract uses a library to extend the Solidity bytes32 type to provide push() and find(). The method is described in the article “Dynamic Value Arrays in Solidity” by the author.

Solidity’s mapping feature is used to map from the given address to a bytes32 variable, which holds a compound of each given role that the address provides.

This implementation will throw an exception if the smart contract using it attempts to add more than 31 roles to any one account. That’s impossible in our particular implementation, but please be aware of the limitation if you use this technique.

map/set

Here is the last useful import file providing a base contract that provides the add and check functions:

contract BaseAccountRolesSet { // an account has many roles

mapping(address => uint) accountRoleSet;



function addAccountRole(address account, uint role) internal {

accountRoleSet[account] |= 1 << role;

} function confirmAccountRole(address account, uint role) internal

view returns (bool) {

return (accountRoleSet[account] & (1 << role)) != 0;

}

}

Solidity’s mapping feature is used to map from the given address to a variable, which is used as a set to holds each given role that the address provides.

This implementation will not throw an exception if the smart contract using it attempts to add more than 256 roles to any one account. I’m relaxed about that possibility in this case.

Enigmatic picture opportunity:
['Jules Goddard']
['Smart Contracts', 'Solidity', 'Blockchain Technology', 'Ethereum', 'Programming']