> Aztec.nr API reference, v6.0.0 (mainnet and testnet). Index: https://docs.aztec.network/aztec-nr-api/v6.0.0/llms.txt

# Function only_self

Module: `noir_aztec::macros::functions`

```rust
pub comptime fn only_self(f: FunctionDefinition)
```

Restricts an [`external`](/aztec-nr-api/v6.0.0/noir_aztec/macros/functions/fn.external.md) function so that it can only be called by the contract itself.

[`external`](/aztec-nr-api/v6.0.0/noir_aztec/macros/functions/fn.external.md) 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`](/aztec-nr-api/v6.0.0/noir_aztec/macros/functions/fn.only_self.md) similarly makes it so that the only authorized address is the account contract, i.e. the function *requires* reentrancy.

These are different from [`internal`](/aztec-nr-api/v6.0.0/noir_aztec/macros/functions/fn.internal.md) 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`](/aztec-nr-api/v6.0.0/noir_aztec/macros/functions/fn.external.md) 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`](/aztec-nr-api/v6.0.0/noir_aztec/macros/functions/fn.only_self.md) 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`](/aztec-nr-api/v6.0.0/noir_aztec/macros/functions/fn.only_self.md) 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`](/aztec-nr-api/v6.0.0/noir_aztec/macros/functions/fn.only_self.md) 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`](/aztec-nr-api/v6.0.0/noir_aztec/macros/functions/fn.only_self.md) 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 [`external`](/aztec-nr-api/v6.0.0/noir_aztec/macros/functions/fn.external.md) [`only_self`](/aztec-nr-api/v6.0.0/noir_aztec/macros/functions/fn.only_self.md) public function. The [`only_self`](/aztec-nr-api/v6.0.0/noir_aztec/macros/functions/fn.only_self.md) 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.

## Initialization Checks

`only_self` functions implicitly skip initialization checks (as if they had [`noinitcheck`](/aztec-nr-api/v6.0.0/noir_aztec/macros/functions/fn.noinitcheck.md)). We want `only_self` functions to be callable during initialization, so we can't have them check the initialization nullifier since it would fail.

This is safe because `only_self` functions can be called only by the contract the function is in, meaning execution must start with another external function in the same contract. Eventually the call stack reaches the `only_self` function, but let's focus on that external entry point:

- If it already performed an initialization check, then we are safe.
- If it skipped the initialization check (via [`noinitcheck`](/aztec-nr-api/v6.0.0/noir_aztec/macros/functions/fn.noinitcheck.md)), then the contract developer is explicitly choosing to not check for initialization, and so will our `only_self` function. That's a design choice by the developer. If we didn't skip the initialization check on `only_self`, the developer would just add `noinitcheck` to it anyway.
- If it was the initializer, note that initialization nullifiers are emitted at the end of initialization: the private initialization nullifier after all private execution, and the public one after all public execution. So in terms of initialization checking, everything behaves as if the contract hasn't been initialized yet, and the same two points above still apply.
