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
externalfunction so that it can only be called by the contract itself.externalfunctions can normally be called by any address - it is up to contracts to set up access control checks e.g. to admin functions.only_selfsimilarly makes it so that the only authorized address is the account contract, i.e. the function requires reentrancy.These are different from
internalfunctions 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
externalfunctions, so there are multiple scenarios to consider.Private
Private functions can only be externally called by other private functions. In this case,
only_selfcan 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_selfexternal 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 beonly_selfbecause 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_selfcalls are rare and not very useful (it'd be equivalent to anexternalSolidity 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
externalonly_selfpublic function. Theonly_selfattribute 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.