|
2 | 2 | // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd |
3 | 3 | pragma solidity ^0.8.25; |
4 | 4 |
|
| 5 | +/// MUST be thrown by an `IAuthorizeV1` contract if the user is not authorized. |
| 6 | +/// @param user The address of the user that was not authorized. |
| 7 | +/// @param permission The permission that was not granted. |
| 8 | +/// @param data The data that was passed to the authorization contract. |
5 | 9 | error Unauthorized(address user, bytes32 permission, bytes data); |
6 | 10 |
|
| 11 | +/// Minimal interface for a contract to provide authorization for another. |
| 12 | +/// The contract implementing this is expected to REVERT if the user is not |
| 13 | +/// authorized for the given permission. There are no return values. |
| 14 | +/// |
| 15 | +/// There's no assumption that the authorization works in any particular way. A |
| 16 | +/// simple example would be an RBAC such as implemented by Open Zeppelin's |
| 17 | +/// standard contracts. A more complex example would be handing over the |
| 18 | +/// authorization to a rainlang expression that could be voted on and deployed |
| 19 | +/// by a DAO. |
| 20 | +/// |
| 21 | +/// The point is that the calling contract can decouple its basic workflows and |
| 22 | +/// associated state from the authorization logic. This is in contract to the |
| 23 | +/// `Ownable` pattern where the calling contract would expect itself to be owned |
| 24 | +/// by some contract that implements the authorization logic as a wrapper. The |
| 25 | +/// main benefit of `IAuthorizeV1` is that the authorization contract can be |
| 26 | +/// passed contextual data about state changes from the caller, without |
| 27 | +/// duplication of sensitive internal logic. |
| 28 | +/// |
| 29 | +/// If the `Ownable` pattern is desirable for whatever reason, the `IAuthorizeV1` |
| 30 | +/// contract can simply revert whenever the caller is not the owner. |
| 31 | +/// |
| 32 | +/// Obviously, setting the `IAuthorizeV1` contract on the caller is an extremely |
| 33 | +/// sensitive operation and should be done with care, such as through a multisig |
| 34 | +/// and/or dedicated governance contract. |
7 | 35 | interface IAuthorizeV1 { |
| 36 | + /// Authorize a user for a caller-specified permission. |
| 37 | + /// |
| 38 | + /// The authorization contract is expected to be implemented to be compatible |
| 39 | + /// with a specific caller only. It MUST be aware of and handle all |
| 40 | + /// `permission` values that the caller may send. |
| 41 | + /// |
| 42 | + /// Authorization MAY CHANGE STATE as `view` is NOT mandated at the interface |
| 43 | + /// level, however it is RECOMMENDED. For example, a user may only be |
| 44 | + /// authorized to perform an action a specified number of times, and so the |
| 45 | + /// authorization contract will need to maintain a counter. However, if state |
| 46 | + /// changes are allowed, the authorization contract MUST enforce that the |
| 47 | + /// caller is the expected contract, otherwise it is very likely that state |
| 48 | + /// will be corrupted by a malicious caller. |
| 49 | + /// |
| 50 | + /// @param user The address of the user to authorize. Most likely will be |
| 51 | + /// the `msg.sender` from the calling contract's perspective, but MAY NOT be. |
| 52 | + /// @param permission The permission to authorize. |
| 53 | + /// @param data Arbitrary data to pass to the authorization contract. Most |
| 54 | + /// likely to be an abi encoded representation of the state change that the |
| 55 | + /// caller needs to authorize. |
8 | 56 | function authorize(address user, bytes32 permission, bytes memory data) external; |
9 | 57 | } |
0 commit comments