Published in


Authorizable — Ethereum Smart Contracts Governance Made Easy

We are in the early stage of smart contract development, and things that are normal in centralized software development are just going to happen in the decentralized world. Governance is one of those things.

An example: CryptoKitties

The CryptoKitties smart contract is at https://etherscan.io/address/0x06012c8cf97bead5deae237070f9587f8e7a266d#code. If you take a look at the code, you will see how they solved the governance extending where needed the contract KittyAccessControl:

contract KittyAccessControl {
address public ceoAddress;
address public cfoAddress;
address public cooAddress;

modifier onlyCEO() {
require(msg.sender == ceoAddress);

modifier onlyCFO() {
require(msg.sender == cfoAddress);

modifier onlyCOO() {
require(msg.sender == cooAddress);

modifier onlyCLevel() {
msg.sender == cooAddress ||
msg.sender == ceoAddress ||
msg.sender == cfoAddress

function setCEO(address _newCEO) external onlyCEO {
require(_newCEO != address(0));

ceoAddress = _newCEO;

function setCFO(address _newCFO) external onlyCEO {
require(_newCFO != address(0));

cfoAddress = _newCFO;

function setCOO(address _newCOO) external onlyCEO {
require(_newCOO != address(0));

cooAddress = _newCOO;

This approach works in this context because the contract cannot be modified. A better approach to smart contract development is to allow the contract to evolve, as summarized by Jack Tanner in this post:

Doing so, you need some general approach to governance that allows flexibility while keeping the contract safe. An advanced solution is AragonOS:

In the post above, Jorge Izquierdo writes about upgradeability:

Smart contract upgradeability is a topic we spend a lot of time thinking about at Aragon. We need to ensure that the organizations that run Aragon will be securely available for years to come.

When I first thought about Authorizable, I made the same reflection. My solution is not as sophisticated as AragonOS, but it is simpler and effortless to implement.

The Authorizable smart contract

First off, you can look at the code at https://github.com/tweedentity/authorizable/blob/master/contracts/Authorizable.sol

Any wallet able to perform something in a smart contract has an assigned level. The level is a uint256, which means that you can manage a huge amount of levels and combine them to do everything you want.

To simplify your life, though, you’d probably prefer to set a limited number of levels. For this reason, there are two special variables with a reasonable default value:

uint public maxLevel = 64;  
uint public authorizerLevel = 56;

The second is the minimum level required to authorize other wallets. The only restriction is that as soon as you authorize a wallet, to keep the contract consistent, you won’t be able to change these two variables.

When you have set some roles, you’ve a bunch of self-explaining useful modifiers:

onlyOwner        // inherited by ZeppelinOS’s Ownable
onlyAuthorizedAtLevel(uint _level)
onlyAuthorizedAtLevels(uint[] _levels)
onlyAuthorizedAtLevelsWithin(uint _minLevel, uint _maxLevel)
onlyOwnerOrAuthorizedAtLevel(uint _level)
onlyOwnerOrAuthorizedAtLevels(uint[] _levels)
onlyOwnerOrAuthorizedAtLevelsWithin(uint _minLevel, uint _maxLevel)

It could have set a generic modifier with many options, but I thought that it was better to explicitly cover all the primary cases without adding exoteric modifiers. You can always add some in your contract.

The CryptoKitties case

First off, they didn’t need KittyAccessControl because Authorizable covers all their needs.

In KittyAccessControl they considered three roles that in our case could be:

CEOLevel: 60 // able to authorize other wallets because >= 56
CTOLevel: 50
CFOLevel: 40

To authorize the ceoAddress the owner could call:

authorize(ceoAddress, 60);

After, ceoAddress could do the same to authorize cfoAddress and ctoAddress. Then, in the contract, the following function

function withdrawBalance() external onlyCFO {

would be

function withdrawBalance() external onlyAuthorizedAtLevel(40) {

The advantage is clear. CryptoKitties is growing. In the future, there could be an entire department working on financials. In this case, it is very likely that there will be more than one address authorized to do that job. Using Authorizable that’s easy; using the actual CryptoKitties contract that’s impossible.

Finally, the onlyClevel modifier would be substituted like:

uint[] Clevels = [40, 50, 60];function setSecondsPerBlock(uint256 secs) external
onlyAuthorizedAtLevels(Clevels) {

I’ll write in a future post about use cases (for example: whitelists), bringing some practical example. In the meantime, what do you think? Any suggestion, comment, or pull request is very welcome.

If you like this post, please 👏 and share it!

A Cryptocurrency Experiment in the Internet of Money

Recommended from Medium

Why Use a Blockchain as a Service (BaaS)? — MyBlockchainExperts

A Retrospective on the Across Launch and What’s Next

Proof of ESG — NFTs for a Cleaner Future

Porta Ecosystem Grant Winner — EvidenZ

Cudos Private Testnest Update — Cognitum 🧠

Why Syscoin is the ideal layer 1

Blockchain Brought to the Grocery Industry! INS Revolutionising the Ecosystem for FMCG Companies

The Third Storeman Group Begins February 1st, 2021 — Don’t Forget to Register Your Node!

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Francesco Sullo

Francesco Sullo

Polymath. Before founded @Passpack, and was at @Turo, @Yahoo, @Tronfoundation and others. More at https://francesco.sullo.co

More from Medium

Tokensoft — Web3 Platform For Token Sales

Social Media Services and Technologies Towards Web 3.0

Creating a token on Solana + add a market ( {Token}/USDC)

The Future Roadmap of EOS