Disclaimer: This is a summary of patterns we have observed during our research and should not be considered any form of technical or investment advice. Also, the given “known examples” do not imply they are the best implementations of the said pattern or any superior to any other implementation of the pattern not listed.
Restrict invocation of individual functions in the smart contract to a permissioned set of accounts by embedding permission controls into the contract.
By default, all the smart contracts running on the blockchain can be accessed and called by all the network participants and other smart contracts due to equal rights. However, most applications require only a permissioned set of accounts to be able to call relevant smart contract functions.
A smart contract by default has no owner, meaning that once deployed the deployer of the smart contract has no special privilege on the smart contract. A permission-less function can be triggered by unauthorised users. For example, a permission-less function discovered in a smart contract library used by the Parity multi-sig wallet caused the freezing of about 500K Ether. How to ensure only a permissioned account(s) can invoke a smart contract function?
- Security – The functions defined in a smart contract should be called only by the authorised participants. Due to the transparency and equal rights of public blockchains, all the smart contracts are also publicly available to everyone connecting to the Internet. In contrast, in a conventional software system, interactions are either through a user interface or API, where it is possible to enforce access control policies.
- Cost – Permission checking introduce additional logic into a smart contract. On public blockchains, higher transaction fees need to be paid to execute complex smart contract logic.
The solution is to track and enforce who can access what function(s) on a smart contract. Add access control to every smart contract function to check whether the caller has permission to call the function. Authorised callers can be defined as a list of account addresses. Then at run time, the transaction sender’s address should be first checked against the list of authorised addresses. If there is a match, the rest of the smart contract logic could be executed. Otherwise, the function should not execute further.
Embedded permission pattern
If a set of smart contract functions depend on the same set of authorised addresses and/or follow the same validation logic, it could be implemented as a separate function and bind to each function. For example, in Solidity, function modifiers are used to change or restrict the behaviour of a smart contract function. In public blockchains, smart contract data can be read without calling respective read-only functions (the process is a bit complicated but can be done). Hence, no additional security is achieved by embedding permissions into read-only functions. However, such constraints are still effective when users do not have direct access to a blockchain node to query such public data. For example, this is effective in consortium blockchains when a user does not run a node. As a general practice, all functions that can modify ledger data must enforce permissions. Permissions could be enforced using access control techniques such as mandatory, role-based, and attribute-based access control. While it is possible to update the list of authorised account addresses after deploying a smart contract, additional functionality is needed to do so. Further, updates should be performed only by an authorised address(es).
- Security – Only the participants and smart contracts that are authorised by the smart contract can call the corresponding functions successfully. The authorisation is implemented in smart contracts running on blockchain, which leverages the properties provided by blockchain.
- Cost – On a public blockchain, extra code that implements the permission control mechanism introduce additional deployment and run-time costs.
- Lack of flexibility – Permissions need to be defined in the smart contract before its deployment hence they are difficult to change. However, permissions may be required to be dynamic. A mechanism is needed to support dynamic granting and removal of permissions.
- Multiple authorisation pattern enables a set of addresses to show their permission to execute a smart contract function.
- Off-chain secret enabled dynamic authorisation allows dynamic binding of an authorised party to a smart contract function.
- The Mortal contract discussed in the Solidity tutorial restricts the permission of invoking the selfdestruct function to the owner of the contract where owner is a variable defined in the contract code itself.
- The Restrict access pattern suggested in the Solidity tutorial uses modifier to restrict who can make modifications to the state of the contract or call the functions of the contract.