Restricts an external function so that it can only be called by the contract itself.
external functions can normally be called by any address - it is up to contracts to set up access control checks
e.g. to admin functions. only_self similarly makes it so that the only authorized address is the account contract,
i.e. the function requires reentrancy.
These are different from internal functions in that those are internally called, i.e. they don't result in
contract calls.
Use Cases
This attribute can be applied to both private or public external functions, so there are multiple scenarios to
consider.
Private
Private functions can only be externally called by other private functions. In this case, only_self can be used to
recursively call circuits, achieving proving time performance improvements for low-load scenarios.
For example, consider a token transfer for some amount: the number of notes that need to be read and nullified is
not known at compile time. Selecting a large maximum number of notes to read per transfer would result in a large
circuit with excess capacity in transfers of few notes, while a small maximum would outright prevent many notes from
being used at once.
A better approach is to create a private only_self external function in which notes are read and nullified,
recursively calling itself if the sum of the values does not add up to some target amount. This makes the circuit
adapt itself to the number of notes required, resulting in either few or many recursive invocations and therefore
proving time roughly proportional to the number of notes. The recursive function must be only_self because we
want to prevent any other contract from calling it - it is only an internal mechanism.
Public
Public functions can only be externally called by both private and public functions. Public to public only_self
calls are rare and not very useful (it'd be equivalent to an external Solidity function with
require(msg.sender == address(this))). Private to public calls do enable useful design patterns though.
A private function that needs to perform some public check (like some public state assertion) or follow-up public
action (like some public state mutation) can do so by enqueuing a call to an externalonly_self public function.
The only_self attribute will prevent external callers from invoking the function, making it be a purely internal
mechanism.
A classic example is a private mint function in a token, which would require an enqueued public call in which the
total supply is incremented.
Restricts an external function so that it can only be called by the contract itself.
external functions can normally be called by any address - it is up to contracts to set up access control checks e.g. to admin functions. only_self similarly makes it so that the only authorized address is the account contract, i.e. the function requires reentrancy.
These are different from internal functions in that those are internally called, i.e. they don't result in contract calls.
Use Cases
This attribute can be applied to both private or public external functions, so there are multiple scenarios to consider.
Private
Private functions can only be externally called by other private functions. In this case, only_self can be used to recursively call circuits, achieving proving time performance improvements for low-load scenarios.
For example, consider a token transfer for some amount: the number of notes that need to be read and nullified is not known at compile time. Selecting a large maximum number of notes to read per transfer would result in a large circuit with excess capacity in transfers of few notes, while a small maximum would outright prevent many notes from being used at once.
A better approach is to create a private only_self external function in which notes are read and nullified, recursively calling itself if the sum of the values does not add up to some target amount. This makes the circuit adapt itself to the number of notes required, resulting in either few or many recursive invocations and therefore proving time roughly proportional to the number of notes. The recursive function must be only_self because we want to prevent any other contract from calling it - it is only an internal mechanism.
Public
Public functions can only be externally called by both private and public functions. Public to public only_self calls are rare and not very useful (it'd be equivalent to an
externalSolidity function withrequire(msg.sender == address(this))). Private to public calls do enable useful design patterns though.A private function that needs to perform some public check (like some public state assertion) or follow-up public action (like some public state mutation) can do so by enqueuing a call to an external only_self public function. The only_self attribute will prevent external callers from invoking the function, making it be a purely internal mechanism.
A classic example is a private mint function in a token, which would require an enqueued public call in which the total supply is incremented.