Skip to content

Groups, Consortiums & Network Governance

Smart Contract Enabled Network Governance

The Enterprise Ethereum Alliance exists to support enterprise-grade extensions of Ethereum-based blockchain networks, which include modifications for scalability, security, and privacy. These implementations are required to provide application-level permissioning and credential management. Our hope is to realize transaction and contract privacy by implementing peer-node and user-level permissioning to control which parties may read and write transactions on a network.

We use smart contracts as access control lists to enact a permissioning standard and implement network privacy. Companies may create new networks by selecting a governance contract which will govern the process to invite new users to the network, as well as assigning varying levels of permissions to user types. New networks will be bootstrapped with an initial node IP, an admin address, a list of initial users (optional), and an initial account balance for all users. This information will be added to the genesis block of the new network.

Simple Corporate Governance Solution

To enable a simple corporate governance solution, you could create one or more private chains consisting of organizational level members and then you could control user roles and access to that chain using a series of user and role permissioning smart contracts. For smaller organizations and implementations, this approach is the easiest governance solution.

For example, one contract could create a list of user roles:

contract UserRole {
  enum UserRole {

Another contract could attribute permissions to those user roles:

ONLY the admin can create users or remove users
ONLY the executive can invite new members
import "./UserRole.sol";
import "./UserPermission.sol";

contract UserRolePermissions is UserRole, TUserPermission {
  uint[] rolePermissions;
  constructor() public {

    rolePermissions[uint(UserRole.ADMIN)] =
      (1 << uint(TtPermission.CREATE_USER)) ;
      (1 << uint(TtPermission.REMOVE_USER)) ;

    rolePermissions[uint(UserRole.EXECUTIVE] =
      (1 << uint(TtPermission.INVITE_MEMBER)) ;

    rolePermissions[uint(UserRole.GUEST)] = 0;

  function getRolePermissions(TtRole _role) public view returns (uint) {
    return rolePermissions[uint(_role)];

Enterprise Corporate Governance

For enterprise clients, a more comprehensive corporate governance solution can be configured by working with our support engineers for a custom solution. Although implementations may vary slightly, this section sets out the terms and concepts applied for those implementations.


  • Entity Operating on Network (EON) – the Entity Operating the blockchain Network (e.g. an operating organization; and admin at such an organization; some voting quorum of participants in a network)
  • Enterprise Participant (EP) – an Enterprise Participant of the blockchain network
  • Entity - a company
  • User - human operators
  • Groups - collection of users, domain of administration
  • Network - collections of groups and their associated nodes. The network decides collectively on which subnet to include, and those subsets dictate which nodes they allow.

Contracts Bundle

Our contracts governance solution involves four components, each managed by separate contracts:

  • Users represent humans

  • Groups represent a team of humans

  • Networks represent a consortium, i.e. a competitive set of cooperative teams

  • MembershipDeciders dictate the specific rules of a consortium.


The Users contract is self contained in contracts/User.sol. Users should be initialized with a readable name and email address of the person they represent. The email address is intended to be a way of verifying the identity of other users in the consortium, who may not belong to the same team. After an initial connection through email, Users are encouraged to seek authentication through whatever means they deem appropriate. The vouchFor method can be used to provide a network level reputation and confidence that the User is a faithful representation.


The Groups contract in contracts/Group.sol represents a team of Users and their permissions. A Group can comprise an individual, a department, or an entire company. When addUser expands a Group, the newest member is given permissions that are the intersection of the User inviting them and the permissions the inviter wants them to have. The permissions (listed in contracts/Permission.sol) reflect the different ways that the Users of the Group can act on its behalf. At present time, the rights in use are:

  • CAN_ADD_USER: the ability to add any User to this group

  • CAN_REMOVE_USER: the ability to remove any User that is a current member from this group

  • CAN_{ADD,REMOVE}_NODE: For the current Networks that this group is a part of (see below), the ability to {add, remove} authorized servers.

  • CAN_{INVITE,UNINVITE}_MEMBER: For the current Networks of this group, the ability to nominate other Groups to join or to vote for those Groups to be evicted.

  • CAN_CREATE_NETWORK: The ability to construct a Network contract.

  • CAN_PROPOSE_DECIDER: The ability to nominate a new MembershipDecider for this Network.

As those permissions hint at, Groups have nodes in addition to Users. However, while Users are intrinsic to a Group the nodes of a Group depend on a Network as context. For example, Group g can have nodes x, y in Network n, and nodes y, z in Network m. but g must have Users a,b in both n and m.


Networks are a collection of Groups. Each Group supplies a list of nodes as enode URLs, with the intent that this network contract is used as a permissions model for servers allowed to connect to this blockchain. If a Group belongs to a Network, any User with CAN_ADD_NODE can augment the node list for that Group.

To add Groups to a network, every Group that already belongs can vote for their membership through invite and uninvite. This pair of functions will record the desire of that Group, but it is up to the MembershipDecider to choose when to alter the roster of the network.

Groups can have WRITE or READ permissions in the context of a Network. Currently, only groups with WRITE permission can call mutating transactions of the Network. It may be beneficial to granularize this, so that read only members can for example expand the list of nodes they own. On the other hand, EVM nodes are also welcome to reject transactions from READ only groups as their original intention is to facilitate audits.


MembershipDeciders customize the bylaws of a Network. They have 3 callbacks:

  • inviteApproved returns 2 when the Group should now have write access, 1 for read access, and 0 for no access

  • inviteRevoked returns true when the Group should be evicted.

  • swapDecider returns true when the Network should upgrade its MembershipDecider

A handful of basic MembershipDeciders are included. To list briefly their form:

  • Static: Groups are included or removed. The decider will never allow itself to be changed out.

  • AutoApprove: Groups are automatically included or removed when invited. The decider will swap the first time it is asked

  • AdminRun: the Network has an admin Group, which is the only vote that counts for approving/revoking/swapping.

  • MajorityRules: A prospective Group needs more than half of the current Groups to invite it for membership. A propspective MembershipDecider needs more than half of the current Groups to nominate it before this MembershipDecider will relinquish control to it.

How this functions is that the Network records relevant state for elections in public variables, and makes calls to the MembershipDecider address it currently has to ask about when to mutate itself.

The MembershipDecider answers questions by examining the state of its caller, i.e. the Network.

What this accomplishes is that Networks are upgradable in a way that preserves state, and furthermore that said upgrade can be customized for the needs of the consortium it's representing.

Creating a Network

Initiating a Network During Node Startup

A network registry contract can be preloaded onto the genesis block. This contract will be used as a library to query network membership, and will enable the dashboard interface to allow authorized participants to add and remove users.

Genesis Network Inclusion

A feature here to establish the authority of a Network over any is the inclusion of a bootstrapping Network in the genesis block. The Genesis Ingestion Tool is capable of inserting Users, Groups, Networks, and MembershipDeciders at prechosen addresses, so there is no confusion over the authoritative Network. By default, the addresses are

  • 0x100000000: Network
  • 0x100000001: MembershipDecider
  • 0x200000000 and up: Groups
  • 0x300000000 and up: Users

The genesis.json file generated can then be shared to prospective participants, so they a) will have a convergent blockchain and b) can deny transactions from any non-bootstrap node until they can see the current state of the Network as a full participant.

Customizing the Genesis Block

  • --decider_bytecode_file will determine the initial rules of the network. It should point to a bin-runtime, which can be generated with e.g. solc --bin-runtime MajorityRules.sol.
  • Deciding upon a guestlist to start the network with. The format of that guest list is a json file that is a list of objects, where each object has the following fields:

  • user_address: The address for an account that this user owns. This is not to be confused with the address of the User contract. The User contract will be at say 0x30000000f, but in order for this user_address to be useful the owner should have a private key for it.

  • user_email: Contact details for this user.
  • user_name: Human readable name.
  • group_name: The name for the Group they will be made admin of from the start of the blockchain.
  • node_url: an enode formatted URL representing a server that this user is operating.

See data/participants.json for an example of this file format, and see for an example of how to compile the contracts, create a genesis.json file, and start up geth with that genesis configuration.

Creating a Private Network within an Existing Network

See the Private Chain section for more details.

Adding Members to an Existing Network

Accept Member into Network

An admin of an EP will onboard a new EP by navigating to the membership.sol contract and calling the function addMember with the EP address and role as a parameter.

Additionally, an admin of an EP may delegate responsibility to endorse a prospective member by calling the function delegateSigning with a peer-EP address and participant address as parameters. This function will require the assigned user to sign a transaction (endorsing the prospective member to be included) on the membership contract in order for the new EP to be submitted to the members array.

Controlling and Monitoring Nodes

Whitelist Node

An admin of an EP will whitelist a new node by calling the function addNode in the registry contract with the node address and role as a parameter.

Additionally, an admin of an EON will be able to delegate whitelisting of a new EP node to the EP administrator by calling the delegateSigning function with the EP administrator’s address and role as a parameter.

Blacklist Node

An EON admin may add an EP to the blacklist by calling the function removeNode with the EP address as a parameter.

Node Monitoring

An EON administrator will be able to monitor the number of IPs of eNodes of the nodes spun by any EP by viewing the activeNodes state on the registry contract, returning the number of nodes and addresses.

Resource Monitoring

An EON administrator will be able to monitor the resource (gas) consumption of EPs by calling the gasCount function in the contract, which returns the list of transactions per EP and a sum of gas used.

Onboarding Workflow

Suppose Alice is a member of a running Network. How would she invite Bob to join them, if he isn't able to connect yet? The procedure is as follows:

  1. Alice sends an off-chain message to Bob, with the genesis.json file.
  2. Bob responds with the same data in participants.json. In particular, an ethereum address and a node_url.
  3. Alice calls the User constructor with Bob's address, name, and email
  4. Alice calls the Group constructor with Bob's User's address and the group name
  5. Alice then invites Bob's Group to the Network, and encourages other members to as well.
  6. Alice let's Bob know when the membership has been approved.
  7. Bob then starts a node up at the IP address in the enode URL with the private key that will give it the same public key in the enode URL. The node should start up with the genesis.json that Alice sent him in the first step.
  8. Bob imports the private key to that running node, so he can authenticate as the address he had provided Alice in step 2.