June 4, 2026

Capitalizations Index – B ∞/21M

Role Based Access Control for the Ethereum Blockchain

Role Based Access Control for the Ethereum Blockchain

Historically, privacy was almost implicit, because it was hard to find and gather information. But in the digital world we need to have more explicit rules. — Bill Gates

Introduction

Role Based Access Control is a security need for software systems that are designed to be accessed by hundreds of users. While this need is commonly implemented in enterprise software and operating systems, not much has been done for the Ethereum Blockchain.

This article aims to show how we implemented Role Based Access Control in Solidity for the Ethereum Blockchain, and to teach you to build your own. We also have made our code public, please feel free to reuse it in any way or form.

When designing a Supply Chain as a Directed Acyclic Graph we realised that we needed to determine dynamically who could add information to each node in the graph. From a real world perspective if you own a manufacturing facility you probably want all operators in the assembly line to record with their own account that they have assembled a part.

OpenZeppelin, who I use as the gold standard in solidity development, have a Roles.sol contract that they use to implement roles such as Minter and Burner in their ERC721.sol contracts. Unfortunately these implementations don’t allow to create new roles at runtime, which you need if you want to control access to each separate token using separate roles.

This article aims to show how you can build a Role Based Access Control System for the Ethereum Blockchain.

I ended just coding a RBAC contract from scratch according to our requirements, before finding an discontinued version of the same idea from OpenZeppelin which had pretty much the very same methods. In the interest of reusability I refactored my code as much as I could to follow their nomenclature.

In the following sections I will describe:

  • The design requirements for our access control system;
  • the implementation as a smart contract;
  • the test cases we considered;
  • the gas usage of state changing methods
  • and some finishing thoughts.

Let’s dig in.

Conceptual Design

My idea for an RBAC system was simple.

  1. Roles would be identified by a numeric identifier like groups in unix.
  2. Roles could be created dynamically with just a description.
  3. Each role would store the addresses of users.
  4. Each role would have a second role associated, which would be the only one allowed to add or remove users.

If you are using the Roles.sol and RBAC.sol contracts from OpenZeppelin you need to be aware that Roles.sol only implements operations that take effect inside a role, while operations that happen outside the role are implemented in RBAC.sol or the access/roles/*Role.sol contracts, including the data structure to store roles as you create them.

In my implementation I took a number of decisions tailored to our use case:

  1. I include a description string inside the Role struct, with the structs themselves stored in an array. The position of each Role struct in the array is used as an identifier. There is a temptation to use a mapping to store the Roles, but I find it unnecessary.
  2. Each role receives on instantiation the identifier of another role which we designate as its admin role and which cannot be modified after instantiation. This admin role is the only one that can add and remove bearers to this role.
  3. The bearers of each role are stored in an array inside the Role struct, instead of a mapping as in many contracts that store users. Since I expect to have many roles with few users this should be efficient enought and this way I can retrieve a list of all bearers for security audits.
  4. For security and consistency reasons you can remove a Bearer from a Role, but there is no method to remove a Role completely from the system.

In my implementation I took a number of implementation tailored to our use case.

The use of arrays instead of mappings makes the code more verbose, unfortunately. More compact or gas efficient implementations surely exist, but this one passes all my tests and I prefer to code for clarity until optimizations are strongly demanded.

Implementation

/**
* @title RBAC
* @author Alberto Cuesta Canada
* @notice Implements runtime configurable Role Based Access Control.
*/
contract RBAC
    /**
* @notice All roles ever created.
*/
Role[] public roles;
    /**
* @notice The contract constructor, empty as of now.
*/
constructor() public
    /**
* @notice Create a new role.
* @dev If the _admin parameter is the id of the newly created
* role msg.sender is added to it automatically.
* @param _roleDescription The description of the role being
* created.
* @param _admin The role that is allowed to add and remove
* bearers from the role being created.
* @return The role id.
*/
function addRole
(
string memory _roleDescription,
uint256 _admin
)
public
returns(uint256)
)
) - 1;
emit RoleCreated(role);
if (_admin == role)
return role;
}
    /**
* @notice Verify whether an address is a bearer of a role
* @param _account The account to verify.
* @param _role The role to look into.
* @return Whether the account is a bearer of the role.
*/
function hasRole
(
address _account,
uint256 _role
)
public
view
returns(bool)

return false;
}
    /**
* @notice Add a bearer to a role
* @param _account The address to add as a bearer.
* @param _role The role to add the bearer to.
*/
function addBearer
(
address _account,
uint256 _role
)
public

}
    /**
* @notice Remove a bearer from a role
* @param _account The address to remove as a bearer.
* @param _role The role to remove the bearer from.
*/
function removeBearer
(
address _account,
uint256 _role
)
public

}
}
}

Testing

I always describe the tests passed when making a contract public, both to show the edge cases and to provide some confidence as to the reliability of the code. In response to previous feedback, I’m now including as well a gas usage report using eth-gas-reporter.

Contract: RBAC
RBAC
✓ addRootRole creates a role.
✓ hasRole returns false for non existing roles.
✓ hasRole returns false for non existing bearerships.
✓ addRootRole adds msg.sender as bearer.
✓ addRole doesn’t add msg.sender with admin role.
✓ addBearer reverts on non existing roles.
✓ addBearer reverts on non authorized users.
✓ addBearer exits if the bearer belongs to the role.
✓ addBearer adds a bearer to a role.
✓ removeBearer throws on non existing roles.
✓ removeBearer throws on non authorized users.
✓ removeBearer exits if the bearer doesn't belong to the role.
✓ removeBearer removes a bearer from a role.

Conclusion

This article describes an implementation for a Smart Contract Role Based Access Control System, which has the following properties:

  1. Allows new roles to be created at runtime.
  2. Includes a concept of role administrator, which is allowed to add and remove members to the role.
  3. Allows to easily determine all existing roles and their bearers.

Role Based Access Control is not necessarily complex to implement, but as this article shows there are a number of trade-offs and design decisions that need to be taken into account, which will be closely related to your users and the actions that they are allowed to perform. While I would be very pleased if you decide to reuse this implementation of an RBAC system, I encourage you to look for and consider other options.

For a practical application of this RBAC contract, stay tuned for the next article in our Supply Chain series.

Published at Mon, 06 May 2019 09:44:14 +0000

Previous Article

Bitcoin Price Wobbles As Trump China Trade Dispute Hits Asian Markets

Next Article

Bitcoin [BTC]: Bitfinex IEO token supply will negatively affect King Coin in the short term, Fundstrat’s Lee

You might be interested in …

Localbitcoins to introduce new user verification rules

Localbitcoins to Introduce New User Verification Rules

Localbitcoins to Introduce New User Verification Rules Peer-to-peer crypto exchange Localbitcoins is preparing to implement updated requirements for the identity verification of its users. The company recently revealed it’s cooperating with regulatory agencies in Finland […]

Re: 揭校园贷"利滚利"陷阱:借800元 20天后被迫还20万

Re: 揭校园贷"利滚利"陷阱:借800元 20天后被迫还20万

Re: 揭校园贷"利滚利"陷阱:借800元 20天后被迫还20万 校园贷本是一种学生助学和创业的贷款平台。 近年来,学生因向校园贷借款而背负上巨额欠款的新闻屡屡被爆出,学生因还不上欠款辍学自杀的事件也时有发生。 一位学生家长林先生告诉记者:儿子第一次校园贷的借款是800元,利滚利后,到现在,他背负的债务,已是近20万元了! 校园贷借来的钱花着爽还着却很苦,短短20多天,800元欠款竟然滚到20万元!学生家长:家里面再怎么穷也不能让小孩去借高利贷! 校园贷横行,轻易套牢大学生 一个普通的学生是怎样背负上这巨额债务的呢?“校园贷”又是如何一步步套牢大学生的呢?  拆东墙补西墙,越补漏洞越大 林先生介绍,当借款金额累计到合同签订的两万元上限,这时上一家放贷人就会将借款人债务转移到下一家放贷人。 为了还钱,林先生儿子也丧失了理智,同时向多个放贷人借款,这让他的债务爆炸式上升!   林先生儿子一笔借款的年利率高达1300%,再加上每一次借款还要给一笔不小数额的上门放款费和上一家放贷人的介绍费,800元的借款要滚到二十多万不会要太长的时间。 林先生儿子几天煎熬之后,才向家里人说明情况。林先生说,他也曾经想过报警,但是在借款时,儿子向放贷人登记了家庭、学校、老师、同学的联系方式,有的同学还录制借款视频。 林先生担心放贷人采取不法或极端方式讨债,影响儿子学习,甚至威胁儿子的人身安全,所以才选择妥协。 (Why?) Published at Mon, 10 Apr 2017 05:06:12 +0000 [wpr5_ebay kw=”bitcoin” num=”1″ ebcat=”” cid=”5338043562″ lang=”en-US” country=”0″ sort=”bestmatch”]{flickr|100|campaign}