From aa18195286cd7d8a1685617d5b01f2b306f487b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Wed, 29 Oct 2025 19:12:22 +0000 Subject: [PATCH 1/4] docs about contract structure --- .../framework-description/contract-scope.md | 14 -- .../contract-structure.md | 140 +++++++++++++++++- .../aztec-nr/framework-description/index.md | 4 +- 3 files changed, 133 insertions(+), 25 deletions(-) delete mode 100644 docs/pages/aztec-nr/framework-description/contract-scope.md diff --git a/docs/pages/aztec-nr/framework-description/contract-scope.md b/docs/pages/aztec-nr/framework-description/contract-scope.md deleted file mode 100644 index 68e4437..0000000 --- a/docs/pages/aztec-nr/framework-description/contract-scope.md +++ /dev/null @@ -1,14 +0,0 @@ -# Contract Scope - -## Mike's Notes - -- Discuss: - - how to declare a contract. - - Differences vs conventional Noir program. - - Essential imports - - Describe limitations (no inheritance, currently, so big monolithic contract files) - - This will change significantly next year, after Noir 1.0 is audited and launched. - -## Ciara's notes - -Literally like they syntax of how to create a contract in Noir. E.g. in solidity we would explain the `contract` keyword, explain the scope that its sorta like a class and that you have to name it :) \ No newline at end of file diff --git a/docs/pages/aztec-nr/framework-description/contract-structure.md b/docs/pages/aztec-nr/framework-description/contract-structure.md index bde8e39..1bed0fb 100644 --- a/docs/pages/aztec-nr/framework-description/contract-structure.md +++ b/docs/pages/aztec-nr/framework-description/contract-structure.md @@ -1,12 +1,136 @@ # Contract Structure -## Mike's comments +high level structure of how contracts are written and what they're made of -1. High-level structure - - Imports - - Contract Scope - - State Variables - - Functions - - Events - - See the dedicated section below +(i am not sure if there should be links throughout this page to the different relevant sections, eg state vars, events, functions, etc., or if we should just do the entire thing in one go with much more detail. i am writing this as if you had never seen a contract in your life and needed to get a sense of how the thing sort of looks to wrap your head around it. there'd be some minor content duplication between this page and the dedicated page in that case - i think that's fine) +## contract block + +all contracts begin the same: + +```noir +// import the `aztec` macro from aztecnr +use aztec::macros::aztec; + +// use the 'contract' keyword to declare a contract, applying the `aztec` macro +#[aztec] +contract MyContract { + // contract code here +} +``` + +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 things like 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. + +## Imports + +except for 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 . + +```noir +use aztec::macros::aztec; + +#[aztec] +contract MyContract { + // other imports go here + use aztec::state_vars::{PrivateMutable, PrivateSet}; +} +``` + +>note: noir's vscode extension 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, and 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, there are multiple _kinds_ of state variables. we do this by defining a `struct` 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_. + +```noir +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]` struct 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 { + // 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, + // 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, + } +} +``` + +>all contract state must be in a single struct. the #[storage] macro can only be used once + +## Events + +same as in solidity, aztec contracts can define events which notify people that something has happened. in aztec however events can also be emitted privately, in which case only some users will learn of the event. + +events are simply a struct marked with the `#[event]` macro: +```noir +#[event] +struct Transfer { + from: AztecAddress, + to: AztecAddress, + amount: 128, +} +``` + +## 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 run on the user's device, producing a zero knowledge proof 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) as they process transactions +- external utility functions, which are executed 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 + +```noir +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. + +// show an internal fn being called from one or two external ones. this feature is not yet complete in aztecnr + +### 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. \ No newline at end of file diff --git a/docs/pages/aztec-nr/framework-description/index.md b/docs/pages/aztec-nr/framework-description/index.md index ec35ff4..b7711b2 100644 --- a/docs/pages/aztec-nr/framework-description/index.md +++ b/docs/pages/aztec-nr/framework-description/index.md @@ -1,5 +1,3 @@ # Framework Description -## Ciara's notes - -- An overview of the contents (like a bullet point clickable list) \ No newline at end of file +(i am not entirely sure what'd go here. is this just a repeat of the sidebar with some minor descriptions? do we even need such a thing, specially if we're thinking about having a single scrollable page for the entire contract section in aztecnr?) \ No newline at end of file From 6a0204780710ac7c713da98d5e1ebafc1bbaa567 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Venturo?= Date: Wed, 29 Oct 2025 17:02:16 -0300 Subject: [PATCH 2/4] Update contract-structure.md --- .../framework-description/contract-structure.md | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/docs/pages/aztec-nr/framework-description/contract-structure.md b/docs/pages/aztec-nr/framework-description/contract-structure.md index 1bed0fb..a8f7c54 100644 --- a/docs/pages/aztec-nr/framework-description/contract-structure.md +++ b/docs/pages/aztec-nr/framework-description/contract-structure.md @@ -21,11 +21,11 @@ contract MyContract { 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 things like 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. +>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. (link to docs on noir crates and workspaces) ## Imports -except for 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 . +except for 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 (link to noir modules). ```noir use aztec::macros::aztec; @@ -51,7 +51,7 @@ contract MyContract { } ``` -in aztec this process is a bit more involved, as not only are there both private and public variables, there are multiple _kinds_ of state variables. we do this by defining a `struct` 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_. +in aztec this process is a bit more involved, as not only are there both private and public variables, there are multiple _kinds_ of state variables. we do this by defining a `struct` (link to noir 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_. ```noir use aztec::macros::aztec; @@ -63,7 +63,7 @@ contract MyContract { state_vars::{PrivateMutable, PublicMutable} }; - // the storage struct can have any name, but it is typically just called `Storage`. it must have the `#[storage]` struct applied to it. + // 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 { @@ -75,8 +75,6 @@ contract MyContract { } ``` ->all contract state must be in a single struct. the #[storage] macro can only be used once - ## Events same as in solidity, aztec contracts can define events which notify people that something has happened. in aztec however events can also be emitted privately, in which case only some users will learn of the event. @@ -133,4 +131,4 @@ all #[external] contract functions must be defined _directly inside the `contrac 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. \ No newline at end of file +we expect to lift some of these restrictions sometime after the release of noir 1.0. From 643e9954d8ea29daa832455fb2cb43b5f17ddfb1 Mon Sep 17 00:00:00 2001 From: Ciara Nightingale Date: Mon, 3 Nov 2025 16:05:14 +0000 Subject: [PATCH 3/4] fix the build --- .../aztec-nr/framework-description/contract-structure.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/pages/aztec-nr/framework-description/contract-structure.md b/docs/pages/aztec-nr/framework-description/contract-structure.md index a8f7c54..d29eb74 100644 --- a/docs/pages/aztec-nr/framework-description/contract-structure.md +++ b/docs/pages/aztec-nr/framework-description/contract-structure.md @@ -51,7 +51,7 @@ contract MyContract { } ``` -in aztec this process is a bit more involved, as not only are there both private and public variables, there are multiple _kinds_ of state variables. we do this by defining a `struct` (link to noir 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_. +in aztec this process is a bit more involved, as not only are there both private and public variables, there are multiple _kinds_ of state variables. we do this by defining a `struct` (link to noir 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_ (link). ```noir use aztec::macros::aztec; @@ -106,17 +106,17 @@ contract MyContract { #[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) { - ... + // ... } } ``` From bdf571451c5f7de36e94ee76e6dddf2473ba6fb4 Mon Sep 17 00:00:00 2001 From: Ciara Nightingale Date: Mon, 3 Nov 2025 16:07:27 +0000 Subject: [PATCH 4/4] remove the index.md for framework-description --- docs/pages/aztec-nr/framework-description/index.md | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 docs/pages/aztec-nr/framework-description/index.md diff --git a/docs/pages/aztec-nr/framework-description/index.md b/docs/pages/aztec-nr/framework-description/index.md deleted file mode 100644 index b7711b2..0000000 --- a/docs/pages/aztec-nr/framework-description/index.md +++ /dev/null @@ -1,3 +0,0 @@ -# Framework Description - -(i am not entirely sure what'd go here. is this just a repeat of the sidebar with some minor descriptions? do we even need such a thing, specially if we're thinking about having a single scrollable page for the entire contract section in aztecnr?) \ No newline at end of file