Introducing EIP-1480: Access Control Standard

matan tsuberi
DAOstack
4 min readOct 15, 2018

--

EIP-1480: Access Control Standard is a capability-based security mechanism for Ethereum smart contracts, created by the DAOstack team, that allows the developer to easily define complex role-based, ordering (i.e requiring f(..) to be called before g(..)), timing, and use-count constraints for accessing the functionality of the contract in a secured way without compromising gas costs.

EIPs are Ethereum Improvement Proposals — proposals for improving the core protocol specifications, client APIs, and contract standards of the Ethereum network.

What is capability-based security?

Capability-based security makes an explicit analogy between how physical items are secured in the physical world and how to optimize computer security. In the physical world, restricting access to a resource means putting some kind of lock on it and distributing keys to authorized agents. Having the capability to access the resource means possessing a key that opens the resource’s lock. An important property of this approach is that keys can’t be forged by an unauthorized agent.

In the context of the Blockchain, we can treat a contract’s methods as the resources under protection and we can code up rules that ensure the same properties as above. Locks are implemented as simple bytes32 IDs and keys are simply stored in a map that tracks which address has a key for which id.

How it works

We created a contract that tracks which accounts are in possession of which keys.

Key parameters can include answers to the following questions::

  1. Is it assignable to other accounts?
  2. From what time it can be used? (can be immediately)
  3. When will it expire? (optional)
  4. How many times it can be used? (can be infinite)

All capabilities are ultimately granted from the contract, by using the grantKey method. Accounts can then assignKeypart or all of their capabilities to other accounts (if allowed).

Quick example

Our simple example is of a company who wants to recruit employees via an external HR company and pay those employees a fixed salary regularly each month. Let’s see how we can use the Permissioned base contract and take advantage of access control to make solving this problem a breeze.

Start by inheriting from Permissioned:

contract Company is Permissioned {}

We grant the creator of the contract (presumably the CEO) the ability to manage HR companies for the company:

constructor(address _coo) {
// The sender has unlimited access to `manageHRCompany`
grantFullKey(“manageHRCompany”, msg.sender)
coo = _coo;
}

Here we define what it means to manage HR companies, and we also give HR companies the ability to register employees:

function hireHRCompany(address _hrCompany, uint nEmployees)    
public
guarentee(unlock(“manageHRCompany”))
{
// Allow the hrCompany to register up to `nEmployees`
grantKey(
“registerEmployee”,
_hrCompany,
false, // not assignable to other accounts
0, // effective immediately
0, // no expiration
nEmployees // can be used up to `nEmployees` times
);
}
function fireHRCompany(address _hrCompany)
public
guarentee(unlock(“manageHRCompany”))
{
// Revoke access to `registerEmployee`
revokeOwnerKey(“registerEmployee”, _hrCompany);
}

At registerEmployee, we register the employee and grant the COO the ability to pay this employee in a month from now.

function registerEmployee(address _employee, uint _salary)
public
guarentee(unlock("registerEmployee"))
{
// register the employee, set last pay date to now
// Next payday for this employee is at least a month from now
grantKey(
keccak256("payout", _employee),
COO,
true, // assignable to other accounts
now + 30 days, // can be called in at least a month from now
0, // no expiration
1 // one time use
);
}

and this is what payout looks like:

function payout(address _employee)
public
// The sender can payout to this employee
gurentee(unlock(keccak256("payout", _employee)))
{
// payout for the duration from last pay date...
// Next payday is at least a month from now
grantKey(
keccak256("payout", _employee),
COO,
true, // assignable to other accounts
now + 30 days, // can be called in at least a month from now
0, // no expiration
1 // one time use
);
}

Take a look at the full example.

ERC165-compatible (interface id: 0x33f9cb64)

ERC165 is a standard that allows contracts and clients to programmatically check whether a contract implements a given interface. Making the Permissioned contract ERC165-compatible means that clients (both contracts and DApps) can programmatically check if a contract is Permissioned.

Our EIP

Looking at the Ethereum ecosystem we see a lot of standards emerging that make developing DApps efficient and easy. When talking about access control, we have seen a few attempts to standardize various small aspects, such as Ownable for having an account with privileged capabilities and ERC1261 for managing membership in an organization. We believe approaches like this can be vastly improved upon by standardizing most use cases under a single interface specification. This will allow increased flexibility, interoperability and standard tooling support. Take a look at the specification & discussion here.

Future directions

Here are some promising ideas we intend to develop in the future:

  1. User Groups — The ability to grant/assign/revoke keys to collections of accounts with a single method call.
  2. Contract as a service — Implementing a singleton contract that globally manages locks & keys for all contracts will allow contracts to share locks for a given method and interact in more sophisticated ways.
  3. The ability to programmatically know what the lock conditions are for a given method and check if an account is able to access it.

Learn More / Get Involved

--

--