Skip to content
Open
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
6c2e981
add aztec-nr overview
ciaranightingale Jan 12, 2026
51d2f09
contract structure
ciaranightingale Jan 12, 2026
4a02e83
wip
ciaranightingale Jan 12, 2026
8b14e78
wip
ciaranightingale Jan 16, 2026
02b7c02
merged content I'm happy with
ciaranightingale Jan 19, 2026
a12250f
Merge branch 'next' into docs/nico-changes
ciaranightingale Jan 19, 2026
907cb04
add some as include_code but its not that great tbh...
ciaranightingale Jan 20, 2026
ffd4bfc
fix build
ciaranightingale Jan 20, 2026
5b3212c
Merge branch 'next' into docs/nico-changes
ciaranightingale Jan 20, 2026
c31dab0
Nico's requested changes
ciaranightingale Jan 22, 2026
8d7cb45
Update docs/docs-developers/docs/aztec-nr/framework-description/contr…
ciaranightingale Jan 22, 2026
11e0a71
Update docs/docs-developers/docs/aztec-nr/framework-description/state…
ciaranightingale Jan 22, 2026
a33f9ee
Update docs/docs-developers/docs/aztec-nr/framework-description/state…
ciaranightingale Jan 22, 2026
c5ef29b
Update docs/docs-developers/docs/aztec-nr/framework-description/state…
ciaranightingale Jan 22, 2026
376a69e
cleanup the Overview
ciaranightingale Jan 22, 2026
3831e2e
syntax
ciaranightingale Jan 22, 2026
30ff4df
wrong #include_code
ciaranightingale Jan 22, 2026
3db4fd8
duplicate content
ciaranightingale Jan 22, 2026
a1acbae
grammar
ciaranightingale Jan 22, 2026
c66f2b8
merge next
ciaranightingale Jan 22, 2026
f2495c3
Update noir-projects/noir-contracts/contracts/test/test_contract/src/…
ciaranightingale Jan 28, 2026
80cc7d9
Update docs/docs-developers/docs/aztec-nr/framework-description/contr…
ciaranightingale Jan 28, 2026
d779e34
Update docs/docs-developers/docs/aztec-nr/framework-description/contr…
ciaranightingale Jan 28, 2026
ae2c484
Update docs/docs-developers/docs/aztec-nr/framework-description/contr…
ciaranightingale Jan 28, 2026
c2d5cde
Update docs/docs-developers/docs/aztec-nr/index.md
ciaranightingale Jan 28, 2026
bda37a9
Update docs/docs-developers/docs/aztec-nr/index.md
ciaranightingale Jan 28, 2026
5738ee4
Update docs/docs-developers/docs/aztec-nr/framework-description/contr…
ciaranightingale Jan 28, 2026
3ec8e7e
modify redirect
ciaranightingale Jan 28, 2026
8b4f821
Update docs/docs-developers/docs/aztec-nr/framework-description/contr…
ciaranightingale Jan 28, 2026
242c219
Merge branch 'docs/nico-changes' of https://github.com/AztecProtocol/…
ciaranightingale Jan 28, 2026
ee4df0d
requested changes
ciaranightingale Jan 28, 2026
b8e25ac
add api refs
ciaranightingale Jan 29, 2026
60d9094
add to devnet docs
ciaranightingale Jan 29, 2026
c1660ac
fix build
ciaranightingale Jan 29, 2026
351dd30
add private state variable api refs (forgot hehe)
ciaranightingale Jan 29, 2026
8d575aa
Merge branch 'next' into docs/nico-changes
ciaranightingale Jan 29, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,7 @@ description: Learn the fundamental structure of Aztec smart contracts including
references: ["docs/examples/contracts/counter_contract/src/main.nr"]
---

A contract is a collection of persistent [state variables](./how_to_define_storage.md) and [functions](./functions/index.md) which may manipulate these variables. Functions and state variables within a contract's scope are said to belong to that contract.

A contract can only access and modify its own state. If a contract wishes to access or modify another contract's state, it must make a call to an external function of the other contract. For anything to happen on the Aztec network, an external function of a contract needs to be called.

## Contract

A contract is declared using the `#[aztec]` attribute and the `contract` keyword. By convention, contracts are named in `PascalCase`.

#include_code setup /docs/examples/contracts/counter_contract/src/main.nr rust

:::info A note for vanilla Noir devs
There is no [`main()`](https://noir-lang.org/docs/getting_started/project_breakdown/#mainnr) function within a Noir `contract` scope. More than one function can be an entrypoint.
:::
High-level structure of how Aztec smart contracts including the different components.

## Directory structure

Expand All @@ -33,8 +21,143 @@ Here's a common layout for a basic Aztec.nr Contract project:

See the vanilla Noir docs for [more info on packages](https://noir-lang.org/docs/noir/modules_packages_crates/crates_and_packages).

## contract block

All contracts start with importing the required files and declaring a contract using the `contract` keyword:

```rust
// import the `aztec` macro from Aztec.nr
use aztec::macros::aztec;

// use the 'contract' keyword to declare a contract, applying the `aztec` macro
#[aztec]
contract MyContract {
// contract code here
}
```

By convention, contracts are named in `PascalCase`.

The `#[aztec]` macro performs a lot of the low-level operations required to take a circuit language like Noir and build smart contracts out of it - including automatically creating external interfaces, inserting standard contract functions, etc. **All Aztec smart contracts must have this macro applied to them.**

**Note:** each Noir crate (package) can only have _a single_ contract. If you are writing a multi-contract system, then each of them needs to be in their own separate crate. To learn more about crates and packages, visit the [Noir documentation](https://noir-lang.org/docs/noir/modules_packages_crates/crates_and_packages).

## Imports

Aside from the `#[aztec]` macro import, all other imports need to go _inside_ the `contract` block - this is because `contract` acts like `mod`, creating a new [module](https://noir-lang.org/docs/noir/modules_packages_crates/modules).

```rust
use aztec::macros::aztec;

#[aztec]
contract MyContract {
// other imports go here
use aztec::state_vars::{PrivateMutable, PrivateSet};
}
```

**Note:** [Noir's VSCode extension](../installation) is able to take care of most imports and put them in the correct place automatically.

## State Variables

With the boilerplate out of the way, it is now the time to begin defining the contract logic. It is recommended to start development by understanding the shape the _state_ of the contract will have:
- Which values will be private?
- Which will be public?
- What properties are required (is mutability or immutability needed? is there a single global value, like a token total supply, or does each user get one, like a balance?).

In Solidity, this is done by simply declaring variables inside of the contract, like so:

```solidity
contract MyContract {
uint128 public my_public_state_variable;
}
```

In Aztec this process is a bit more involved, as not only are there both private and public variables (where now these keywords refer to the privacy of the variable rather than their accessibility), there are multiple _kinds_ of state variables.

We define state using a [`struct`](https://noir-lang.org/docs/noir/concepts/data_types/structs) that will hold the entire contract state. We call this struct _the storage struct_, and each variable inside this struct is called [_a state variable_.](./state_variables)

```rust
use aztec::macros::aztec;

#[aztec]
contract MyContract {
use aztec::{
macros::storage,
state_vars::{PrivateMutable, PublicMutable}
};

// the storage struct can have any name, but it is typically just called `Storage`. it must have the `#[storage]` macro applied to it.
// this struct must also have a generic type called C or Context. for now try to pretend it is not there
#[storage]
struct Storage<C> {
// a private numeric value which can change over time. this value will be hidden, and only people who are shown the secret will be able to know its current value
my_private_state_variable: PrivateMutable<u128, C>,
// a public numeric value which can change over time. this value will be known to everyone. this is equivalent to the solidity example above
my_public_state_variable: PublicMutable<u128, C>,
}
}
```

## Events

As in Solidity, Aztec contracts can define events to notify that some state has changed. However, in Aztec, events can also be emitted privately, in which case, only some users will learn of the event.

Events are a struct marked with the `#[event]` macro:

```rust
#[event]
struct Transfer {
from: AztecAddress,
to: AztecAddress,
amount: u128,
}
```

## Functions

Contracts are interacted with by invoking their `external` functions. There are three kinds of `external` functions:

- External **private** functions, which reveal nothing about their execution and are executed off chain on the user's device, producing a zero-knowledge proof of execution that is sent to the network as part of a transaction.
- External **public** functions, which are invoked publicly by nodes in the network (like any `external` Solidity contract function).
- External **utility** functions, which are executed off chain on the user's device by applications in order to display useful information, e.g. retrieve contract state. These are never part of a transaction.

```rust
use aztec::macros::aztec;

#[aztec]
contract MyContract {
use aztec::macros::functions::external;

#[external("private")]
fn my_private_function(parameter_a: u128, parameter_b: AztecAddress) {
// ...
}

#[external("public")]
fn my_public_function(parameter_a: u128, parameter_b: AztecAddress) {
// ...
}

#[external("utility")]
fn my_utility_function(parameter_a: u128, parameter_b: AztecAddress) {
// ...
}
}
```

Additionally, contracts can also define `internal` functions, which cannot be called by other contracts (like any `internal` Solidity function). These exist to help organize the user's code, reuse functionality, etc.

### Current Limitations

All `#[external]` contract functions must be defined _directly inside the `contract` block_, that is, in the same file. It is possible to define `#[internal]` and helper functions in `mod`s in other files, but not `#[external]` functions.

Additionally, **Noir does not feature inheritance** nor is there currently any other mechanism to extend and reuse contract logic. e.g. it is not possible to take a token contract and extend it to add minting functionality, or to reuse it in a liquidity pool. Like in Vyper, the entire logic must live in a single file.

We expect to lift some of these restrictions sometime after the release of Noir 1.0.

## Next steps

- [Define functions](./functions/index.md) - Learn about private, public, and utility functions
- [Define storage](./how_to_define_storage.md) - Work with persistent state variables
- [Define storage](./state_variables.md) - Work with persistent state variables
- [Compile your contract](../how_to_compile_contract.md) - Build your contract artifact
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Use `#[external("private")]` to create functions that execute privately on user

#include_code increment /docs/examples/contracts/counter_contract/src/main.nr rust

Private functions run in a private context, can access private state, and can read certain public values through storage types like [`DelayedPublicMutable`](../how_to_define_storage.md#delayedpublicmutable).
Private functions run in a private context, can access private state, and can read certain public values through storage types like [`DelayedPublicMutable`](../state_variables.md#delayedpublicmutable).

## Define public functions

Expand Down
Loading
Loading