This EIP specifies a generic authorisation mechanism, which can be used to implement a variety of authorisation patterns, replacing approvals in ERC20, operators in ERC777, and bespoke authorisation patterns in a variety of other types of contract.
Smart contracts commonly need to provide an interface that allows a third-party caller to perform actions on behalf of a user. The most common example of this is token authorisations/operators, but other similar situations exist throughout the ecosystem, including for instance authorising operations on ENS domains. Typically each standard reinvents this system for themselves, leading to a large number of incompatible implementations of the same basic pattern. Here, we propose a generic method usable by all such contracts.
The pattern implemented here is inspired by ds-auth and by OAuth.
The generalised authorisation interface is implemented as a metadata provider, as specified in EIP 926. The following mandatory function is implemented:
function canCall(address owner, address caller, address callee, bytes4 func) view returns(bool);
Where:
- owner
is the owner of the resource. If approved the function call is treated as being made by this address.
- caller
is the address making the present call.
- callee
is the address of the contract being called.
- func
is the 4-byte signature of the function being called.
For example, suppose Alice authorises Bob to transfer tokens on her behalf. When Bob does so, Alice is the owner
, Bob is the caller
, the token contract is the callee
, and the function signature for the transfer function is func
.
As this standard uses EIP 926, the authorisation flow is as follows:
owner
address from the metadata registry contract, which resides at a well-known address.canCall()
with the parameters described above. If the function returns false, the callee reverts execution.Commonly, providers will wish to supply a standardised interface for users to set and unset their own authorisations. They SHOULD implement the following interface:
function authoriseCaller(address owner, address caller, address callee, bytes4 func);
function revokeCaller(address owner, address caller, address callee, bytes4 func);
Arguments have the same meaning as in canCall
. Implementing contracts MUST ensure that msg.sender
is authorised to call authoriseCaller
or revokeCaller
on behalf of owner
; this MUST always be true if owner == msg.sender
. Implementing contracts SHOULD use the standard specified here to determine if other callers may provide authorisations as well.
Implementing contracts SHOULD treat a func
of 0 as authorising calls to all functions on callee
. If authorised
is false
and func
is 0, contracts need only clear any blanket authorisation; individual authorisations may remain in effect.
There are no backwards compatibility concerns.
Example implementation TBD.
Copyright and related rights waived via CC0.