From 071634d57738ac600456061959badaaf32208920 Mon Sep 17 00:00:00 2001 From: James Zaki Date: Thu, 14 Mar 2024 10:54:49 +0000 Subject: [PATCH 01/16] Doc crowdfunding (WIP commit + rebase) --- .../tutorials/crowdfunding/donations.md | 63 +++++++++++++++++++ .../tutorials/crowdfunding/rewards.md | 40 ++++++++++++ docs/sidebars.js | 8 +++ .../crowdfunding_contract/src/main.nr | 6 ++ 4 files changed, 117 insertions(+) create mode 100644 docs/docs/developers/tutorials/crowdfunding/donations.md create mode 100644 docs/docs/developers/tutorials/crowdfunding/rewards.md diff --git a/docs/docs/developers/tutorials/crowdfunding/donations.md b/docs/docs/developers/tutorials/crowdfunding/donations.md new file mode 100644 index 00000000000..f2491d82731 --- /dev/null +++ b/docs/docs/developers/tutorials/crowdfunding/donations.md @@ -0,0 +1,63 @@ +--- +title: Build a donations contract +tags: [developers, tutorial, example] +--- + +In this tutorial we'll create two contracts related to crowdfunding: + +- A crowdfunding contract with two core components + - Fully private donations + - Verifiable withdrawals to the operator +- A reward contract for anyone else to anonymously reward donors + +## Setup + +### Install tools + +Please ensure that the you already have [Installed the Sandbox](https://docs.aztec.network/developers/getting_started/quickstart#install-the-sandbox). + +And if using VSCode, [Install Noir LSP](https://docs.aztec.network/developers/contracts/main#install-noir-lsp-recommended). + +### Create an Aztec project + +Create a new Aztec contract project named "crowdfunding": + +```sh +aztec-nargo new --contract crowdfunding +``` + +Inside the new `crowdfunding` directory you will have a base to implement the Aztec smart contract. + +## Private donations + +1. An "Operator" begins a Crowdfunding campaign (contract), specifying: + +- an existing token address +- their account address +- a deadline timestamp + +2. Any address can donate (in private context) + +- private transfer token from sender to contract +- privately note amount donated (claimable via other contract) + +3. Only the operator can withdraw from fund + +### 1. Create a campaign + +Contract. +#include_code empty-contract /noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr rust + +Constructor. +#include_code constructor /noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr rust + +Storage. +#include_code storage /noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr rust + +Ctrl+click types, ( requires LSP) + +### 2. + +## Implement Rewards + +Continue building a complementary rewards contract [here](./rewards.md). diff --git a/docs/docs/developers/tutorials/crowdfunding/rewards.md b/docs/docs/developers/tutorials/crowdfunding/rewards.md new file mode 100644 index 00000000000..f27dc73d856 --- /dev/null +++ b/docs/docs/developers/tutorials/crowdfunding/rewards.md @@ -0,0 +1,40 @@ +--- +title: Build a rewards contract +tags: [developers, tutorial, example] +--- + +In this section we'll build a reward contract for anyone to anonymously reward donors to a campaign. Build the donations contract [here](./donations.md). + +## Setup + +### Install tools + +Please ensure that the you already have [Installed the Sandbox](https://docs.aztec.network/developers/getting_started/quickstart#install-the-sandbox). + +And if using VSCode, [Install Noir LSP](https://docs.aztec.network/developers/contracts/main#install-noir-lsp-recommended). + +### Create an Aztec project + +Create a new Aztec contract project named "claims": + +```sh +aztec-nargo new --contract claims +``` + +Inside the new `claims` directory you will have a base to implement the Aztec smart contract. + +## Rewarding donors + +1. Anyone can reward donors via a Claim contract +2. Rewarder creates a Claim contract, specifying: + +- the target fund address +- the reward token address + +3. Donors of the target fund can call claim with a Note + +### 1. Create a reward contract + +### 2. + +# Privacy diff --git a/docs/sidebars.js b/docs/sidebars.js index c10514ddbe9..4e9b197b521 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -229,6 +229,14 @@ const sidebars = { "developers/tutorials/writing_token_contract", "developers/tutorials/writing_private_voting_contract", + { + label: "Simple donations contract aa", + type: "category", + items: [ + "developers/tutorials/crowdfunding/donations", + "developers/tutorials/crowdfunding/rewards", + ], + }, { label: "Writing a DApp", type: "category", diff --git a/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr b/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr index 71102fda1a9..ce2bec86a94 100644 --- a/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr @@ -1,4 +1,6 @@ +// docs:start:empty-contract contract Crowdfunding { + // docs:end:empty-contract use dep::aztec::{ protocol_types::{abis::function_selector::FunctionSelector, address::AztecAddress, traits::Serialize}, @@ -19,6 +21,7 @@ contract Crowdfunding { } } + // docs:start:storage #[aztec(storage)] struct Storage { // Token used for donations (e.g. DAI) @@ -30,10 +33,13 @@ contract Crowdfunding { // Notes emitted to donors when they donate (later on used to claim rewards in the Claim contract) claim_notes: PrivateSet, } + // docs:end:storage + // docs:start:constructor #[aztec(public)] #[aztec(initializer)] fn constructor(donation_token: AztecAddress, operator: AztecAddress, deadline: u64) { + // docs:end:constructor storage.donation_token.initialize(donation_token); storage.operator.initialize(operator); storage.deadline.initialize(deadline); From 8cc3ec39146dad9d9b37b0c7c82af14ea5b4a85c Mon Sep 17 00:00:00 2001 From: James Zaki Date: Mon, 15 Apr 2024 12:34:54 +0100 Subject: [PATCH 02/16] fix typo --- .../contracts/writing_contracts/functions/initializers.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/docs/developers/contracts/writing_contracts/functions/initializers.md b/docs/docs/developers/contracts/writing_contracts/functions/initializers.md index a673264a4b3..97499c4dd85 100644 --- a/docs/docs/developers/contracts/writing_contracts/functions/initializers.md +++ b/docs/docs/developers/contracts/writing_contracts/functions/initializers.md @@ -10,8 +10,7 @@ Initializers are regular functions that set an "initialized" flag (a nullifier) ## Annotate with `#[aztec(private)]` and `#[aztec(initializer)]` - -Define your initiaizer like so: +Define your initializer like so: ```rust #[aztec(private)] From 9418a811e55800759f15dd198e1c4be5bd0cab55 Mon Sep 17 00:00:00 2001 From: James Zaki Date: Mon, 15 Apr 2024 12:38:51 +0100 Subject: [PATCH 03/16] update donations tutorial --- .../tutorials/crowdfunding/donations.md | 118 ++++++++++++++++-- .../crowdfunding_contract/src/main.nr | 29 ++++- 2 files changed, 134 insertions(+), 13 deletions(-) diff --git a/docs/docs/developers/tutorials/crowdfunding/donations.md b/docs/docs/developers/tutorials/crowdfunding/donations.md index f2491d82731..4d9a7873f08 100644 --- a/docs/docs/developers/tutorials/crowdfunding/donations.md +++ b/docs/docs/developers/tutorials/crowdfunding/donations.md @@ -10,13 +10,20 @@ In this tutorial we'll create two contracts related to crowdfunding: - Verifiable withdrawals to the operator - A reward contract for anyone else to anonymously reward donors +Along the way you will: + +- Install Aztec developer tools +- Setup a new Noir contract project +- Add base Aztec dependencies +- + ## Setup ### Install tools Please ensure that the you already have [Installed the Sandbox](https://docs.aztec.network/developers/getting_started/quickstart#install-the-sandbox). -And if using VSCode, [Install Noir LSP](https://docs.aztec.network/developers/contracts/main#install-noir-lsp-recommended). +And if using VSCode, see [here](https://docs.aztec.network/developers/contracts/main#install-noir-lsp-recommended) to install Noir LSP and select `aztec-nargo`. ### Create an Aztec project @@ -45,19 +52,116 @@ Inside the new `crowdfunding` directory you will have a base to implement the Az ### 1. Create a campaign -Contract. +#### Initialize + +Rename the contract from `Main`, to `Crowdfunding`. + #include_code empty-contract /noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr rust -Constructor. -#include_code constructor /noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr rust +Replace the example functions with an initializer that takes the required campaign info as parameters. Notice use of `#[aztec(...)]` macros inform the compiler that the function is a public initializer. + +```rust +#include_code init-header /noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr raw + //... +} +``` + +More about initializers [here](../../contracts/writing_contracts/functions/initializers.md). + +#### Dependencies + +When you compile the contracts by running `aztec-nargo compile` in your project directory, you'll notice it cannot resolve `AztecAddress`. (Or hovering over in VSCode) + +```rust +#include_code init-header-error /noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr raw + //... +} +``` + +Add the required dependency by going to your project's `Nargo.toml` file, and adding `aztec` from the `aztec-nr` framework. It resides in the `aztec-packages` mono-repo: + +```rust +[dependencies] +aztec = { git="https://github.com/AztecProtocol/aztec-packages/", tag="#include_aztec_version", directory="noir-projects/aztec-nr/aztec" } +``` + +A word about versions: +- Choose the aztec packages version to match your aztec tools as seen here - `aztec-cli -V` +- Check that your `compiler_version` in Nargo.toml is satisified by your aztec compiler - `aztec-nargo -V` + +More about versions [here](https://docs.aztec.network/developers/versions-updating). + +Inside the Crowdfunding contract definition, use the dependency that defines the address type `AztecAddress` + +```rust +use dep::aztec::{protocol_types::{address::AztecAddress}}; +``` + +The brackets are present since we'll be adding more dependencies of `aztec` and of the `protocol_types`. + +#### Storage + +To retain the initializer parameters in the contract's Storage, we'll need to declare them in a preceding `Storage` struct: -Storage. #include_code storage /noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr rust -Ctrl+click types, ( requires LSP) +There is an additional type, `ValueNote` that we will use later, so also include this at the start of your contract + +```rust +use dep::value_note::value_note::ValueNote; +``` + +Now complete the initializer by setting the storage variables with the parameters: + +#include_code init /noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr rust + +### 2. Taking private donations + +#### Checking campaign duration against the timestamp + +To check that the donation occurs before the campaign deadline, we must access the public `timestamp`. It is one of several [Public Global Variables](https://docs.aztec.network/developers/contracts/references/globals#public-global-variables). + +Declare a public (internal) function + +```rust +#include_code deadline-header /noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr raw + //... +} +``` + +Read the deadline from storage and assert that the `timestamp` from this context is before the deadline + +#include_code deadline /noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr rust + + +Since donations are private, they will have the user's private context which has these [Private Global Variables](https://docs.aztec.network/developers/contracts/references/globals#private-global-variables). So from the private context we must do some extra work to call the (public internal) `_check_deadline` function. + +```rust +#include_code call-check-deadline /noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr raw + + //... +} +``` + +From the private context we call `call_public_function` (more [here](https://docs.aztec.network/developers/contracts/references/aztec-nr/aztec/context/private_context#call_public_function)). Passing the address of the contract and the function signature (name and param types). + +We've not yet added the FunctionSelector type, so do that now + +```rust +use dep::aztec::{protocol_types::{address::AztecAddress, abis::function_selector::FunctionSelector}}; +``` + +To see + +#### Simplified interface for tokens + +Note: requires auth-wit of token -### 2. ## Implement Rewards Continue building a complementary rewards contract [here](./rewards.md). + +``` + +``` diff --git a/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr b/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr index ce2bec86a94..23130cddb5c 100644 --- a/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr @@ -30,33 +30,48 @@ contract Crowdfunding { operator: SharedImmutable, // End of the crowdfunding campaign after which no more donations are accepted deadline: PublicImmutable, - // Notes emitted to donors when they donate (later on used to claim rewards in the Claim contract) - claim_notes: PrivateSet, + // Notes emitted to donors when they donate (can be used as proof to obtain rewards, eg in Claim contracts) + donation_receipts: PrivateSet, } // docs:end:storage - // docs:start:constructor + // docs:start:init + // docs:start:init-header + // docs:start:init-header-error #[aztec(public)] #[aztec(initializer)] - fn constructor(donation_token: AztecAddress, operator: AztecAddress, deadline: u64) { - // docs:end:constructor + // this-will-error:init-header-error + fn init(donation_token: AztecAddress, operator: AztecAddress, deadline: u64) { + // docs:end:init-header + // docs:end:init-header-error storage.donation_token.initialize(donation_token); storage.operator.initialize(operator); storage.deadline.initialize(deadline); } + // docs:end:init + // docs:start:deadline + // docs:start:deadline-header #[aztec(public)] #[aztec(internal)] fn _check_deadline() { + // docs:end:deadline-header let deadline = storage.deadline.read(); assert(context.timestamp() < deadline, "Deadline has passed"); } + // docs:end:deadline + // docs:start:donate + // docs:start:call-check-deadline + // docs:start:call-check-deadline-header #[aztec(private)] fn donate(amount: u64) { + // docs:end:call-check-deadline-header // 1) Check that the deadline has not passed Crowdfunding::at(context.this_address())._check_deadline().enqueue(&mut context); + // docs:end:call-check-deadline + // docs:start:do-transfer // 2) Transfer the donation tokens from donor to this contract Token::at(storage.donation_token.read_private()).transfer( context.msg_sender(), @@ -64,12 +79,14 @@ contract Crowdfunding { amount as Field, 0 ).call(&mut context); + // docs:end:do-transfer // 3) Create a value note for the donor so that he can later on claim a rewards token in the Claim // contract by proving that the hash of this note exists in the note hash tree. let mut note = ValueNote::new(amount as Field, context.msg_sender()); - storage.claim_notes.insert(&mut note, true); + storage.donation_receipts.insert(&mut note, true); } + // docs:end:donate // Withdraws balance to the operator. Requires that msg_sender() is the operator. #[aztec(private)] From 4de414edb32b5a89b4c473224147f6ffb60c446b Mon Sep 17 00:00:00 2001 From: James Zaki Date: Tue, 16 Apr 2024 15:56:15 +0100 Subject: [PATCH 04/16] Add references to source --- .../tutorials/crowdfunding/donations.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/docs/docs/developers/tutorials/crowdfunding/donations.md b/docs/docs/developers/tutorials/crowdfunding/donations.md index 4d9a7873f08..9a54caf3d51 100644 --- a/docs/docs/developers/tutorials/crowdfunding/donations.md +++ b/docs/docs/developers/tutorials/crowdfunding/donations.md @@ -94,10 +94,10 @@ More about versions [here](https://docs.aztec.network/developers/versions-updati Inside the Crowdfunding contract definition, use the dependency that defines the address type `AztecAddress` ```rust -use dep::aztec::{protocol_types::{address::AztecAddress}}; +use dep::aztec::protocol_types::address::AztecAddress; ``` -The brackets are present since we'll be adding more dependencies of `aztec` and of the `protocol_types`. +The `aztec::protocol_types` can be browsed [here](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/noir-projects/noir-protocol-circuits/crates/types/src). #### Storage @@ -111,6 +111,8 @@ There is an additional type, `ValueNote` that we will use later, so also include use dep::value_note::value_note::ValueNote; ``` +This dependency is from the top-level of the Aztec.nr framework, namely [noir-projects/aztec-nr](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/noir-projects/aztec-nr/value-note/src/value_note.nr) + Now complete the initializer by setting the storage variables with the parameters: #include_code init /noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr rust @@ -138,20 +140,20 @@ Since donations are private, they will have the user's private context which has ```rust #include_code call-check-deadline /noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr raw - - //... + //... } ``` -From the private context we call `call_public_function` (more [here](https://docs.aztec.network/developers/contracts/references/aztec-nr/aztec/context/private_context#call_public_function)). Passing the address of the contract and the function signature (name and param types). +From the private context we call `call_public_function` (defined in [private_context.nr](https://github.com/AztecProtocol/aztec-packages/tree/master/noir-projects/aztec-nr/aztec/src/context) ~[here](https://docs.aztec.network/developers/contracts/references/aztec-nr/aztec/context/private_context#call_public_function)~). Passing the address of the contract and the function signature (name and param types). -We've not yet added the FunctionSelector type, so do that now +We've not yet added the `FunctionSelector` type, so do that now ```rust use dep::aztec::{protocol_types::{address::AztecAddress, abis::function_selector::FunctionSelector}}; ``` -To see +Like before, you can find the `FunctionSelector`, and other `aztec::protocol_types` [here](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/noir-projects/noir-protocol-circuits/crates/types/src). + #### Simplified interface for tokens From 310b41e189ee0766dfffb6495621319c5e5d93d2 Mon Sep 17 00:00:00 2001 From: James Zaki Date: Thu, 18 Apr 2024 14:58:26 +0100 Subject: [PATCH 05/16] Update tut --- .../tutorials/crowdfunding/donations.md | 34 ++++++++++++------- .../crowdfunding_contract/src/main.nr | 2 -- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/docs/docs/developers/tutorials/crowdfunding/donations.md b/docs/docs/developers/tutorials/crowdfunding/donations.md index 9a54caf3d51..411486f340a 100644 --- a/docs/docs/developers/tutorials/crowdfunding/donations.md +++ b/docs/docs/developers/tutorials/crowdfunding/donations.md @@ -15,7 +15,7 @@ Along the way you will: - Install Aztec developer tools - Setup a new Noir contract project - Add base Aztec dependencies -- +- ## Setup @@ -23,11 +23,11 @@ Along the way you will: Please ensure that the you already have [Installed the Sandbox](https://docs.aztec.network/developers/getting_started/quickstart#install-the-sandbox). -And if using VSCode, see [here](https://docs.aztec.network/developers/contracts/main#install-noir-lsp-recommended) to install Noir LSP and select `aztec-nargo`. +And if using VSCode, see [here](https://docs.aztec.network/developers/contracts/main#install-noir-lsp-recommended) to install Noir LSP, where you'll benefit from syntax highlighting, profiling, and more. ### Create an Aztec project -Create a new Aztec contract project named "crowdfunding": +Use `aztec-nargo` in a terminal to create a new Aztec contract project named "crowdfunding": ```sh aztec-nargo new --contract crowdfunding @@ -35,6 +35,8 @@ aztec-nargo new --contract crowdfunding Inside the new `crowdfunding` directory you will have a base to implement the Aztec smart contract. +Use `aztec-nargo --help` to see other commands. + ## Private donations 1. An "Operator" begins a Crowdfunding campaign (contract), specifying: @@ -54,7 +56,9 @@ Inside the new `crowdfunding` directory you will have a base to implement the Az #### Initialize -Rename the contract from `Main`, to `Crowdfunding`. +Open the project in your preferred editor. If using VSCode and the LSP, you'll be able to select the `aztec-nargo` binary to use (instead of `nargo`). + +In `main.nr`, rename the contract from `Main`, to `Crowdfunding`. #include_code empty-contract /noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr rust @@ -91,13 +95,14 @@ A word about versions: More about versions [here](https://docs.aztec.network/developers/versions-updating). -Inside the Crowdfunding contract definition, use the dependency that defines the address type `AztecAddress` +Inside the Crowdfunding contract definition, use the dependency that defines the address type `AztecAddress` (same syntax as Rust) ```rust use dep::aztec::protocol_types::address::AztecAddress; ``` -The `aztec::protocol_types` can be browsed [here](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/noir-projects/noir-protocol-circuits/crates/types/src). +The `aztec::protocol_types` can be browsed [here](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/noir-projects/noir-protocol-circuits/crates/types/src). And like rust dependencies, the relative path inside the dependency corresponds to `address::AztecAddress`. + #### Storage @@ -105,14 +110,18 @@ To retain the initializer parameters in the contract's Storage, we'll need to de #include_code storage /noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr rust -There is an additional type, `ValueNote` that we will use later, so also include this at the start of your contract +The `ValueNote` type is in the top-level of the Aztec.nr framework, namely [noir-projects/aztec-nr](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/noir-projects/aztec-nr/value-note/src/value_note.nr). Like before, you'll need to add the crate to Nargo.toml + +(See [here](https://docs.aztec.network/developers/contracts/resources/dependencies) for common dependencies). + +--- + +Back in main.nr, reference `use` of the type ```rust use dep::value_note::value_note::ValueNote; ``` -This dependency is from the top-level of the Aztec.nr framework, namely [noir-projects/aztec-nr](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/noir-projects/aztec-nr/value-note/src/value_note.nr) - Now complete the initializer by setting the storage variables with the parameters: #include_code init /noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr rust @@ -123,7 +132,7 @@ Now complete the initializer by setting the storage variables with the parameter To check that the donation occurs before the campaign deadline, we must access the public `timestamp`. It is one of several [Public Global Variables](https://docs.aztec.network/developers/contracts/references/globals#public-global-variables). -Declare a public (internal) function +Declare an Aztec function that is public and internal ```rust #include_code deadline-header /noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr raw @@ -135,8 +144,9 @@ Read the deadline from storage and assert that the `timestamp` from this context #include_code deadline /noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr rust +--- -Since donations are private, they will have the user's private context which has these [Private Global Variables](https://docs.aztec.network/developers/contracts/references/globals#private-global-variables). So from the private context we must do some extra work to call the (public internal) `_check_deadline` function. +Since donations are to be private, the donate function will have the user's private context which has these [Private Global Variables](https://docs.aztec.network/developers/contracts/references/globals#private-global-variables). So from the private context we must do some extra work to call the (public internal) `_check_deadline` function. ```rust #include_code call-check-deadline /noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr raw @@ -144,7 +154,7 @@ Since donations are private, they will have the user's private context which has } ``` -From the private context we call `call_public_function` (defined in [private_context.nr](https://github.com/AztecProtocol/aztec-packages/tree/master/noir-projects/aztec-nr/aztec/src/context) ~[here](https://docs.aztec.network/developers/contracts/references/aztec-nr/aztec/context/private_context#call_public_function)~). Passing the address of the contract and the function signature (name and param types). +From the private context we call `call_public_function` (defined [here](https://docs.aztec.network/developers/contracts/references/aztec-nr/aztec/context/private_context#call_public_function)). Passing the address of the contract and the function signature (name and param types). We've not yet added the `FunctionSelector` type, so do that now diff --git a/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr b/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr index 23130cddb5c..dab87692f68 100644 --- a/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr @@ -63,10 +63,8 @@ contract Crowdfunding { // docs:start:donate // docs:start:call-check-deadline - // docs:start:call-check-deadline-header #[aztec(private)] fn donate(amount: u64) { - // docs:end:call-check-deadline-header // 1) Check that the deadline has not passed Crowdfunding::at(context.this_address())._check_deadline().enqueue(&mut context); // docs:end:call-check-deadline From bcce7bc2a3dcd5d319c9a3bb2c2bdac48d202750 Mon Sep 17 00:00:00 2001 From: James Zaki Date: Tue, 23 Apr 2024 12:24:45 +0100 Subject: [PATCH 06/16] docs updated contract interface --- .../tutorials/crowdfunding/donations.md | 34 ++++++++++++------- .../crowdfunding_contract/src/main.nr | 2 ++ 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/docs/docs/developers/tutorials/crowdfunding/donations.md b/docs/docs/developers/tutorials/crowdfunding/donations.md index 411486f340a..fe49d792d4e 100644 --- a/docs/docs/developers/tutorials/crowdfunding/donations.md +++ b/docs/docs/developers/tutorials/crowdfunding/donations.md @@ -146,7 +146,7 @@ Read the deadline from storage and assert that the `timestamp` from this context --- -Since donations are to be private, the donate function will have the user's private context which has these [Private Global Variables](https://docs.aztec.network/developers/contracts/references/globals#private-global-variables). So from the private context we must do some extra work to call the (public internal) `_check_deadline` function. +Since donations are to be private, the donate function will have the user's private context which has these [Private Global Variables](https://docs.aztec.network/developers/contracts/references/globals#private-global-variables). So from the private context there is a little extra to call the (public internal) `_check_deadline` function. ```rust #include_code call-check-deadline /noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr raw @@ -154,26 +154,34 @@ Since donations are to be private, the donate function will have the user's priv } ``` -From the private context we call `call_public_function` (defined [here](https://docs.aztec.network/developers/contracts/references/aztec-nr/aztec/context/private_context#call_public_function)). Passing the address of the contract and the function signature (name and param types). +Namely calling `enqueue` and passing the (mutable) context. -We've not yet added the `FunctionSelector` type, so do that now +Now conclude adding all dependencies to the `Crowdfunding` contract: -```rust -use dep::aztec::{protocol_types::{address::AztecAddress, abis::function_selector::FunctionSelector}}; -``` +#include_code all-deps /noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr rust -Like before, you can find the `FunctionSelector`, and other `aztec::protocol_types` [here](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/noir-projects/noir-protocol-circuits/crates/types/src). +Like before, you can find these and other `aztec::protocol_types` [here](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/noir-projects/noir-protocol-circuits/crates/types/src). -#### Simplified interface for tokens +#### Interfacing with another contract -Note: requires auth-wit of token +The token being used for donations is stored simply as an `AztecAddress` (named `donation_token`). so to easily use it as a token, we let the compiler know that we want the address to have a Token interface. Here we will use a maintained example Token contract. +Add this `Token` contract to Nargo.toml: `aztec = { git="https://github.com/AztecProtocol/aztec-packages/", tag="#include_aztec_version", directory="noir-projects/noir-contracts/contracts/token_contract" }` -## Implement Rewards +With the dependency already `use`d at the start of the contract, the token contract can be called to make the transfer from msg sender to this contract. Note: the user must have authorised this action (concept [here](../../../learn/concepts/accounts/main#authorizing-actions)), example use of `createAuthWit` in 'full donor flow' test [here](../../../../../yarn-project/end-to-end/src/e2e_crowdfunding_and_claim.test.ts). -Continue building a complementary rewards contract [here](./rewards.md). +#### Creating and storing a private receipt note -``` +The last thing to do is create a new value note and add it to the `donation_receipts`. So the full donation function is now -``` +#include_code all-deps /noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr rust + +### 3. Operator withdrawals + + + +## What next? + +If a new token wishes to honour donors with free tokens based on donation amounts, this is possible via the donation_receipts (a `PrivateSet`). +See [claim_contract](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/noir-projects/noir-contracts/contracts/claim_contract). \ No newline at end of file diff --git a/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr b/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr index dab87692f68..ae9826fcb5c 100644 --- a/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr @@ -2,12 +2,14 @@ contract Crowdfunding { // docs:end:empty-contract + // docs:start:all-deps use dep::aztec::{ protocol_types::{abis::function_selector::FunctionSelector, address::AztecAddress, traits::Serialize}, state_vars::{PrivateSet, PublicImmutable, SharedImmutable} }; use dep::value_note::value_note::ValueNote; use dep::token::Token; + // docs:end:all-deps #[aztec(event)] struct WithdrawalProcessed { From 4b4d0a44d113ee27b9bbc482cb4fc925fe127aca Mon Sep 17 00:00:00 2001 From: James Zaki Date: Tue, 23 Apr 2024 12:39:05 +0100 Subject: [PATCH 07/16] docs complete donations --- .../tutorials/crowdfunding/donations.md | 17 ++++++++++++++++- .../contracts/crowdfunding_contract/src/main.nr | 2 ++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/docs/docs/developers/tutorials/crowdfunding/donations.md b/docs/docs/developers/tutorials/crowdfunding/donations.md index fe49d792d4e..2034048103d 100644 --- a/docs/docs/developers/tutorials/crowdfunding/donations.md +++ b/docs/docs/developers/tutorials/crowdfunding/donations.md @@ -126,6 +126,8 @@ Now complete the initializer by setting the storage variables with the parameter #include_code init /noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr rust +You can compile the code so far with `aztec-nargo compile`. + ### 2. Taking private donations #### Checking campaign duration against the timestamp @@ -179,9 +181,22 @@ The last thing to do is create a new value note and add it to the `donation_rece ### 3. Operator withdrawals +The remaining function to implement, `withdraw`, is reasonably straight-forward: +- make sure the address calling is the operator address +- transfer tokens from the contract to the operator +- reveal that an amount has been withdrawn to the operator + +Copy the last function into your Crowdfunding contract: + +#include_code all-operator-withdrawals /noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr rust + +You should be able to compile successfully with `aztec-nargo compile`. + +## Conclusion +For comparison, the full Crowdfunding contract can be found [here](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/noir-projects/noir-contracts/contracts/crowdfunding_contract). -## What next? +### Next steps? If a new token wishes to honour donors with free tokens based on donation amounts, this is possible via the donation_receipts (a `PrivateSet`). See [claim_contract](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/noir-projects/noir-contracts/contracts/claim_contract). \ No newline at end of file diff --git a/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr b/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr index ae9826fcb5c..3b1f7114772 100644 --- a/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr @@ -88,6 +88,7 @@ contract Crowdfunding { } // docs:end:donate + // docs:start:operator-withdrawals // Withdraws balance to the operator. Requires that msg_sender() is the operator. #[aztec(private)] fn withdraw(amount: u64) { @@ -102,4 +103,5 @@ contract Crowdfunding { let event = WithdrawalProcessed { amount, who: operator_address }; context.emit_unencrypted_log(event.serialize()); } + // docs:end:operator-withdrawals } From 4e8937e29ab06393ca6852bcd6fa921bc9ec8064 Mon Sep 17 00:00:00 2001 From: James Zaki Date: Tue, 23 Apr 2024 16:45:54 +0100 Subject: [PATCH 08/16] docs minor fixes --- docs/docs/developers/tutorials/crowdfunding/donations.md | 6 ++++-- docs/sidebars.js | 7 ++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/docs/docs/developers/tutorials/crowdfunding/donations.md b/docs/docs/developers/tutorials/crowdfunding/donations.md index 2034048103d..380145bef6b 100644 --- a/docs/docs/developers/tutorials/crowdfunding/donations.md +++ b/docs/docs/developers/tutorials/crowdfunding/donations.md @@ -15,7 +15,9 @@ Along the way you will: - Install Aztec developer tools - Setup a new Noir contract project - Add base Aztec dependencies -- +- Call between private and public contexts +- Wrap an address with its interface (token) +- Create custom private value notes ## Setup @@ -188,7 +190,7 @@ The remaining function to implement, `withdraw`, is reasonably straight-forward: Copy the last function into your Crowdfunding contract: -#include_code all-operator-withdrawals /noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr rust +#include_code operator-withdrawals /noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr rust You should be able to compile successfully with `aztec-nargo compile`. diff --git a/docs/sidebars.js b/docs/sidebars.js index 4e9b197b521..b091c0b670c 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -230,12 +230,9 @@ const sidebars = { "developers/tutorials/writing_private_voting_contract", { - label: "Simple donations contract aa", + label: "Simple donations contract", type: "category", - items: [ - "developers/tutorials/crowdfunding/donations", - "developers/tutorials/crowdfunding/rewards", - ], + items: ["developers/tutorials/crowdfunding/donations"], }, { label: "Writing a DApp", From a41f699c8929f3b6dc7573f8c5d521f31dc8bcf9 Mon Sep 17 00:00:00 2001 From: James Zaki Date: Tue, 23 Apr 2024 21:51:28 +0100 Subject: [PATCH 09/16] Update docs/docs/developers/tutorials/crowdfunding/donations.md Co-authored-by: josh crites --- docs/docs/developers/tutorials/crowdfunding/donations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/developers/tutorials/crowdfunding/donations.md b/docs/docs/developers/tutorials/crowdfunding/donations.md index 380145bef6b..29cdd3d0fad 100644 --- a/docs/docs/developers/tutorials/crowdfunding/donations.md +++ b/docs/docs/developers/tutorials/crowdfunding/donations.md @@ -50,7 +50,7 @@ Use `aztec-nargo --help` to see other commands. 2. Any address can donate (in private context) - private transfer token from sender to contract -- privately note amount donated (claimable via other contract) +- transaction receipts allow private claims via another contract 3. Only the operator can withdraw from fund From 0c07161bec1831a122ea7ab12e9c6e101902f40f Mon Sep 17 00:00:00 2001 From: James Zaki Date: Tue, 23 Apr 2024 21:51:52 +0100 Subject: [PATCH 10/16] Update docs/docs/developers/tutorials/crowdfunding/donations.md Co-authored-by: josh crites --- docs/docs/developers/tutorials/crowdfunding/donations.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/docs/developers/tutorials/crowdfunding/donations.md b/docs/docs/developers/tutorials/crowdfunding/donations.md index 29cdd3d0fad..a04bac067a2 100644 --- a/docs/docs/developers/tutorials/crowdfunding/donations.md +++ b/docs/docs/developers/tutorials/crowdfunding/donations.md @@ -173,7 +173,11 @@ The token being used for donations is stored simply as an `AztecAddress` (named Add this `Token` contract to Nargo.toml: `aztec = { git="https://github.com/AztecProtocol/aztec-packages/", tag="#include_aztec_version", directory="noir-projects/noir-contracts/contracts/token_contract" }` -With the dependency already `use`d at the start of the contract, the token contract can be called to make the transfer from msg sender to this contract. Note: the user must have authorised this action (concept [here](../../../learn/concepts/accounts/main#authorizing-actions)), example use of `createAuthWit` in 'full donor flow' test [here](../../../../../yarn-project/end-to-end/src/e2e_crowdfunding_and_claim.test.ts). +With the dependency already `use`d at the start of the contract, the token contract can be called to make the transfer from msg sender to this contract. + +:::note +The user must have authorised this action (concept [here](../../../learn/concepts/accounts/main#authorizing-actions)), example use of `createAuthWit` in 'full donor flow' test [here](../../../../../yarn-project/end-to-end/src/e2e_crowdfunding_and_claim.test.ts). +::: #### Creating and storing a private receipt note From 947d1e7478d08d5ee118fdbb390cb8b4cf39dfaf Mon Sep 17 00:00:00 2001 From: James Zaki Date: Tue, 23 Apr 2024 21:52:03 +0100 Subject: [PATCH 11/16] Update docs/docs/developers/tutorials/crowdfunding/donations.md Co-authored-by: josh crites --- docs/docs/developers/tutorials/crowdfunding/donations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/developers/tutorials/crowdfunding/donations.md b/docs/docs/developers/tutorials/crowdfunding/donations.md index a04bac067a2..7af794b5a47 100644 --- a/docs/docs/developers/tutorials/crowdfunding/donations.md +++ b/docs/docs/developers/tutorials/crowdfunding/donations.md @@ -183,7 +183,7 @@ The user must have authorised this action (concept [here](../../../learn/concept The last thing to do is create a new value note and add it to the `donation_receipts`. So the full donation function is now -#include_code all-deps /noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr rust +#include_code donate /noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr rust ### 3. Operator withdrawals From 0f2c8a6ec97beb4242a5b15c18af85f01757adc0 Mon Sep 17 00:00:00 2001 From: James Zaki Date: Tue, 23 Apr 2024 22:05:35 +0100 Subject: [PATCH 12/16] update donation.md from review --- .../developers/tutorials/crowdfunding/donations.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/docs/docs/developers/tutorials/crowdfunding/donations.md b/docs/docs/developers/tutorials/crowdfunding/donations.md index 7af794b5a47..845c1d90b14 100644 --- a/docs/docs/developers/tutorials/crowdfunding/donations.md +++ b/docs/docs/developers/tutorials/crowdfunding/donations.md @@ -171,7 +171,11 @@ Like before, you can find these and other `aztec::protocol_types` [here](https:/ The token being used for donations is stored simply as an `AztecAddress` (named `donation_token`). so to easily use it as a token, we let the compiler know that we want the address to have a Token interface. Here we will use a maintained example Token contract. -Add this `Token` contract to Nargo.toml: `aztec = { git="https://github.com/AztecProtocol/aztec-packages/", tag="#include_aztec_version", directory="noir-projects/noir-contracts/contracts/token_contract" }` +Add this `Token` contract to Nargo.toml: + +``` +aztec = { git="https://github.com/AztecProtocol/aztec-packages/", tag="#include_aztec_version", directory="noir-projects/noir-contracts/contracts/token_contract" } +``` With the dependency already `use`d at the start of the contract, the token contract can be called to make the transfer from msg sender to this contract. @@ -188,9 +192,11 @@ The last thing to do is create a new value note and add it to the `donation_rece ### 3. Operator withdrawals The remaining function to implement, `withdraw`, is reasonably straight-forward: -- make sure the address calling is the operator address -- transfer tokens from the contract to the operator -- reveal that an amount has been withdrawn to the operator +1. make sure the address calling is the operator address +2. transfer tokens from the contract to the operator +3. reveal that an amount has been withdrawn to the operator + +The last point is achieved by emitting an unencrypted event log, more [here](https://docs.aztec.network/developers/contracts/writing_contracts/events/emit_event#unencrypted-events). Copy the last function into your Crowdfunding contract: From 8f7636ebd53e11cd445ec8a3385636b00110ad98 Mon Sep 17 00:00:00 2001 From: James Zaki Date: Tue, 23 Apr 2024 22:06:12 +0100 Subject: [PATCH 13/16] Update docs/docs/developers/tutorials/crowdfunding/donations.md Co-authored-by: josh crites --- docs/docs/developers/tutorials/crowdfunding/donations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/developers/tutorials/crowdfunding/donations.md b/docs/docs/developers/tutorials/crowdfunding/donations.md index 845c1d90b14..1ccc7e3d11a 100644 --- a/docs/docs/developers/tutorials/crowdfunding/donations.md +++ b/docs/docs/developers/tutorials/crowdfunding/donations.md @@ -52,7 +52,7 @@ Use `aztec-nargo --help` to see other commands. - private transfer token from sender to contract - transaction receipts allow private claims via another contract -3. Only the operator can withdraw from fund +3. Only the operator can withdraw from the fund ### 1. Create a campaign From b416074a2d8e579b1cd543cbb79b9396cd42e644 Mon Sep 17 00:00:00 2001 From: James Zaki Date: Tue, 23 Apr 2024 22:08:42 +0100 Subject: [PATCH 14/16] docs remove rewards.md stub --- .../tutorials/crowdfunding/rewards.md | 40 ------------------- 1 file changed, 40 deletions(-) delete mode 100644 docs/docs/developers/tutorials/crowdfunding/rewards.md diff --git a/docs/docs/developers/tutorials/crowdfunding/rewards.md b/docs/docs/developers/tutorials/crowdfunding/rewards.md deleted file mode 100644 index f27dc73d856..00000000000 --- a/docs/docs/developers/tutorials/crowdfunding/rewards.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -title: Build a rewards contract -tags: [developers, tutorial, example] ---- - -In this section we'll build a reward contract for anyone to anonymously reward donors to a campaign. Build the donations contract [here](./donations.md). - -## Setup - -### Install tools - -Please ensure that the you already have [Installed the Sandbox](https://docs.aztec.network/developers/getting_started/quickstart#install-the-sandbox). - -And if using VSCode, [Install Noir LSP](https://docs.aztec.network/developers/contracts/main#install-noir-lsp-recommended). - -### Create an Aztec project - -Create a new Aztec contract project named "claims": - -```sh -aztec-nargo new --contract claims -``` - -Inside the new `claims` directory you will have a base to implement the Aztec smart contract. - -## Rewarding donors - -1. Anyone can reward donors via a Claim contract -2. Rewarder creates a Claim contract, specifying: - -- the target fund address -- the reward token address - -3. Donors of the target fund can call claim with a Note - -### 1. Create a reward contract - -### 2. - -# Privacy From f9f8bd020ca2037adb28a3094d05d6a7e292662d Mon Sep 17 00:00:00 2001 From: James Zaki Date: Wed, 24 Apr 2024 22:13:13 +0100 Subject: [PATCH 15/16] docs fix dep in donations.md --- docs/docs/developers/tutorials/crowdfunding/donations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/developers/tutorials/crowdfunding/donations.md b/docs/docs/developers/tutorials/crowdfunding/donations.md index 1ccc7e3d11a..c6e1a118cd2 100644 --- a/docs/docs/developers/tutorials/crowdfunding/donations.md +++ b/docs/docs/developers/tutorials/crowdfunding/donations.md @@ -174,7 +174,7 @@ The token being used for donations is stored simply as an `AztecAddress` (named Add this `Token` contract to Nargo.toml: ``` -aztec = { git="https://github.com/AztecProtocol/aztec-packages/", tag="#include_aztec_version", directory="noir-projects/noir-contracts/contracts/token_contract" } +token = { git="https://github.com/AztecProtocol/aztec-packages/", tag="#include_aztec_version", directory="noir-projects/noir-contracts/contracts/token_contract" } ``` With the dependency already `use`d at the start of the contract, the token contract can be called to make the transfer from msg sender to this contract. From 515e0316677f1d1c07fdb664e8b4a0c910a07005 Mon Sep 17 00:00:00 2001 From: James Zaki Date: Wed, 24 Apr 2024 22:22:33 +0100 Subject: [PATCH 16/16] docs donation.md as single item in sidebar --- docs/docs/developers/tutorials/crowdfunding/donations.md | 2 ++ docs/sidebars.js | 7 +------ 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/docs/docs/developers/tutorials/crowdfunding/donations.md b/docs/docs/developers/tutorials/crowdfunding/donations.md index c6e1a118cd2..16dcfae5c58 100644 --- a/docs/docs/developers/tutorials/crowdfunding/donations.md +++ b/docs/docs/developers/tutorials/crowdfunding/donations.md @@ -3,6 +3,8 @@ title: Build a donations contract tags: [developers, tutorial, example] --- +# Build a donations contract + In this tutorial we'll create two contracts related to crowdfunding: - A crowdfunding contract with two core components diff --git a/docs/sidebars.js b/docs/sidebars.js index b091c0b670c..0884c74caeb 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -228,12 +228,7 @@ const sidebars = { items: [ "developers/tutorials/writing_token_contract", "developers/tutorials/writing_private_voting_contract", - - { - label: "Simple donations contract", - type: "category", - items: ["developers/tutorials/crowdfunding/donations"], - }, + "developers/tutorials/crowdfunding/donations", { label: "Writing a DApp", type: "category",