Limiting access in smart-contracts
An ethereum smart-contract holds data and allows users to change the state. Most of the time transactions change the data of the sender and hence do not require access right verification as the transaction is verified by the private key.
In some situations, it is important to limit who can execute a function on a smart-contract. Managing an access control list (ACL) for a smart-contract in such a way that it can be updated can be solved in many ways.
OwnerOnly
The simplest ACL rule is the Owned paradigm in which the creator of a contract gets access to all the functions and everybody else has access only to the functions which change their own data.
The best known example is the ERC20 token in which transfer is for everyone but mint is restricted to the owner.
Authority contract
Because the only certainty is change, it is a good idea to outsource the management of the ACL to a contract which can be updated.
The Owned paradigm can not solve situations where logic is required to execute a contract: e.g. a user can change a state if they have enough balance and have been approved by the admin.
One solution is to make every contract is Auth and offers a modifier that checks if the function can be called by the sender of the message:
modifier auth { assert(isAuthorized(msg.sender, msg.sig)); _;}function isAuthorized(address src, bytes4 sig) internal returns (bool) { if (src == address(this)) { return true; } else if (src == owner && authority == Authority(0)) { return true; } else if (authority == Authority(0)) { UnauthorizedAccess(src, sig); return false; } else { return authority.canCall(src, this, sig); }}
The function isAuthorized allows the owner of the contract to execute the function in the absence of an explicit Authority implementation. The Authority contract is an interface with only one function:
contract Authority { function canCall(address src, address dst, bytes4 sig) constant returns (bool);}
Advantages
The nice thing about this paradigm is that by default you get the functionality of an Owned contract and you can specify whatever logic is necessary for limiting the execution of the functions of a contract.
Each call contains the signature of the function which is called. The signature is the first 4 bytes of the SHA3 of the function name. This is how functions are identified on Ethereum and the value is provided alongside the sender as can be seen in the function call in the modifier:
assert(isAuthorized(msg.sender, msg.sig));
The canCall function in the Authority contract can identify precisely which function in what contract has been called and act accordingly. This gives a lot of flexibility.
The downside
The approach which has been chosen here is to remove all privileges to the owner once an Authority has been defined for the contract.
This means that as soon as an Authority has been defined, it must either include a rule for each function or a generic rule that applies when no other can be found.
In short it is a little more work. But I believe it is worth it.