Skip to content

Commit eca1a03

Browse files
sklppy88Esau
andcommitted
feat: add sol support and fix docs examples
docs examples was broken originally, this fixes it and adds sol support Co-authored-by: Esau <[email protected]>
1 parent b8f04e1 commit eca1a03

File tree

17 files changed

+275
-176
lines changed

17 files changed

+275
-176
lines changed

docs/Nargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
members = [
33
"examples/contracts/counter_contract",
44
"examples/contracts/bob_token_contract",
5-
"examples/tutorials/token_bridge_contract/contracts/aztec/nft",
6-
"examples/tutorials/token_bridge_contract/contracts/aztec/nft_bridge"
5+
"examples/contracts/nft",
6+
"examples/contracts/nft_bridge"
77
]

docs/docs-developers/docs/aztec-nr/framework-description/how_to_implement_custom_notes.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ address_note = { git="https://github.com/AztecProtocol/aztec-packages/", tag="#i
5151

5252
Define your custom note with the `#[note]` macro:
5353

54-
#include_code nft_note_struct /docs/examples/tutorials/token_bridge_contract/contracts/aztec/nft/src/nft.nr rust
54+
#include_code nft_note_struct /docs/examples/contracts/nft/src/nft.nr rust
5555

5656
The `#[note]` macro generates the following for your struct:
5757

@@ -98,13 +98,13 @@ struct Storage<Context> {
9898

9999
### Inserting notes
100100

101-
#include_code mint /docs/examples/tutorials/token_bridge_contract/contracts/aztec/nft/src/main.nr rust
101+
#include_code mint /docs/examples/contracts/nft/src/main.nr rust
102102

103103
### Reading and removing notes
104104

105105
Use `pop_notes` to read and nullify notes atomically. This is the recommended pattern for most use cases:
106106

107-
#include_code burn /docs/examples/tutorials/token_bridge_contract/contracts/aztec/nft/src/main.nr rust
107+
#include_code burn /docs/examples/contracts/nft/src/main.nr rust
108108

109109
:::warning
110110
There's also a `get_notes` function that reads without nullifying, but use it with caution - the returned notes may have already been spent in another transaction.

docs/docs-developers/docs/tutorials/js_tutorials/token_bridge.md

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ touch src/nft.nr
108108

109109
In this file, you're going to create a **private note** that represents NFT ownership. This is a struct with macros that indicate it is a note that can be compared and packed:
110110

111-
#include_code nft_note_struct /docs/examples/tutorials/token_bridge_contract/contracts/aztec/nft/src/nft.nr rust
111+
#include_code nft_note_struct /docs/examples/contracts/nft/src/nft.nr rust
112112

113113
You now have a note that represents the owner of a particular NFT. Next, move on to the contract itself.
114114

@@ -134,36 +134,36 @@ Write the storage struct and a simple [initializer](../../foundational-topics/co
134134
<!-- wrapped in a code block to add a "}" at the end -->
135135

136136
```rust
137-
#include_code contract_setup /docs/examples/tutorials/token_bridge_contract/contracts/aztec/nft/src/main.nr raw
137+
#include_code contract_setup /docs/examples/contracts/nft/src/main.nr raw
138138
}
139139
```
140140

141141
### Utility Functions
142142

143143
Add an internal function to handle the `DelayedPublicMutable` value change. Mark the function as public and `#[only_self]` so only the contract can call it:
144144

145-
#include_code mark_nft_exists /docs/examples/tutorials/token_bridge_contract/contracts/aztec/nft/src/main.nr rust
145+
#include_code mark_nft_exists /docs/examples/contracts/nft/src/main.nr rust
146146

147147
This function is marked with `#[only_self]`, meaning only the contract itself can call it. It uses `schedule_value_change` to update the `nfts` storage, preventing the same NFT from being minted twice or burned when it doesn't exist. You'll call this public function from a private function later using `enqueue_self`.
148148

149149
Another useful function checks how many notes a caller has. You can use this later to verify the claim and exit from L2:
150150

151-
#include_code notes_of /docs/examples/tutorials/token_bridge_contract/contracts/aztec/nft/src/main.nr rust
151+
#include_code notes_of /docs/examples/contracts/nft/src/main.nr rust
152152

153153
### Add Minting and Burning
154154

155155
Before anything else, you need to set the minter. This will be the bridge contract, so only the bridge contract can mint NFTs. This value doesn't need to change after initialization. Here's how to initialize the `PublicImmutable`:
156156

157-
#include_code set_minter /docs/examples/tutorials/token_bridge_contract/contracts/aztec/nft/src/main.nr rust
157+
#include_code set_minter /docs/examples/contracts/nft/src/main.nr rust
158158

159159
Now for the magic - minting NFTs **privately**. The bridge will call this to mint to a user, deliver the note using [constrained message delivery](../../aztec-nr/framework-description/how_to_emit_event.md) (best practice when "sending someone a
160160
note") and then [enqueue a public call](../../aztec-nr/framework-description/how_to_call_contracts.md) to the `_mark_nft_exists` function:
161161

162-
#include_code mint /docs/examples/tutorials/token_bridge_contract/contracts/aztec/nft/src/main.nr rust
162+
#include_code mint /docs/examples/contracts/nft/src/main.nr rust
163163

164164
The bridge will also need to burn NFTs when users withdraw back to L1:
165165

166-
#include_code burn /docs/examples/tutorials/token_bridge_contract/contracts/aztec/nft/src/main.nr rust
166+
#include_code burn /docs/examples/contracts/nft/src/main.nr rust
167167

168168
### Compiling!
169169

@@ -241,7 +241,7 @@ Clean up `main.nr` which is just a placeholder, and let's write the storage stru
241241
<!-- wrapped in a code block to add a "}" at the end -->
242242

243243
```rust
244-
#include_code bridge_setup /docs/examples/tutorials/token_bridge_contract/contracts/aztec/nft_bridge/src/main.nr raw
244+
#include_code bridge_setup /docs/examples/contracts/nft_bridge/src/main.nr raw
245245
}
246246
```
247247

@@ -255,7 +255,7 @@ You need to define how to encode messages. Here's a simple approach: when an NFT
255255

256256
Build the `claim` function, which consumes the message and mints the NFT on the L2 side:
257257

258-
#include_code claim /docs/examples/tutorials/token_bridge_contract/contracts/aztec/nft_bridge/src/main.nr rust
258+
#include_code claim /docs/examples/contracts/nft_bridge/src/main.nr rust
259259

260260
:::tip Secret
261261

@@ -265,7 +265,7 @@ The secret prevents front-running. Certainly you don't want anyone to claim your
265265

266266
Similarly, exiting to L1 means burning the NFT on the L2 side and pushing a message through the protocol. To ensure only the L1 recipient can claim it, hash the `token_id` together with the `recipient`:
267267

268-
#include_code exit /docs/examples/tutorials/token_bridge_contract/contracts/aztec/nft_bridge/src/main.nr rust
268+
#include_code exit /docs/examples/contracts/nft_bridge/src/main.nr rust
269269

270270
Cross-chain messaging on Aztec is powerful because it doesn't conform to any specific format—you can structure messages however you want.
271271

@@ -319,7 +319,7 @@ touch contracts/SimpleNFT.sol
319319

320320
Create a minimal NFT contract sufficient for demonstrating bridging:
321321

322-
#include_code simple_nft /docs/examples/tutorials/token_bridge_contract/contracts/SimpleNFT.sol solidity
322+
#include_code simple_nft /docs/examples/solidity/nft_bridge/SimpleNFT.sol solidity
323323

324324
### Create the NFT Portal
325325

@@ -332,15 +332,15 @@ touch contracts/NFTPortal.sol
332332
Initialize it with Aztec's registry, which holds the canonical contracts for Aztec-related contracts, including the Inbox and Outbox. These are the message-passing contracts—Aztec sequencers read any messages on these contracts.
333333

334334
```solidity
335-
#include_code portal_setup /docs/examples/tutorials/token_bridge_contract/contracts/NFTPortal.sol raw
335+
#include_code portal_setup /docs/examples/solidity/nft_bridge/NFTPortal.sol raw
336336
}
337337
```
338338

339339
The core logic is similar to the L2 logic. `depositToAztec` calls the `Inbox` canonical contract to send a message to Aztec, and `withdraw` calls the `Outbox` contract.
340340

341341
Add these two functions with explanatory comments:
342342

343-
#include_code portal_deposit_and_withdraw /docs/examples/tutorials/token_bridge_contract/contracts/NFTPortal.sol solidity
343+
#include_code portal_deposit_and_withdraw /docs/examples/solidity/nft_bridge/NFTPortal.sol solidity
344344

345345
The portal handles two flows:
346346

@@ -383,19 +383,19 @@ This section assumes you're working locally using the local network. For the tes
383383

384384
First, initialize the clients: `aztec.js` for Aztec and `viem` for Ethereum:
385385

386-
#include_code setup /docs/examples/tutorials/token_bridge_contract/scripts/index.ts typescript
386+
#include_code setup /docs/examples/ts/token_bridge/index.ts typescript
387387

388388
You now have wallets for both chains, correctly connected to their respective chains. Next, deploy the L1 contracts:
389389

390-
#include_code deploy_l1_contracts /docs/examples/tutorials/token_bridge_contract/scripts/index.ts typescript
390+
#include_code deploy_l1_contracts /docs/examples/ts/token_bridge/index.ts typescript
391391

392392
Now deploy the L2 contracts. Thanks to the TypeScript bindings generated with `aztec codegen`, deployment is straightforward:
393393

394-
#include_code deploy_l2_contracts /docs/examples/tutorials/token_bridge_contract/scripts/index.ts typescript
394+
#include_code deploy_l2_contracts /docs/examples/ts/token_bridge/index.ts typescript
395395

396396
Now that you have the L2 bridge's contract address, initialize the L1 bridge:
397397

398-
#include_code initialize_portal /docs/examples/tutorials/token_bridge_contract/scripts/index.ts typescript
398+
#include_code initialize_portal /docs/examples/ts/token_bridge/index.ts typescript
399399

400400
The L2 contracts were already initialized when you deployed them, but you still need to:
401401

@@ -404,49 +404,49 @@ The L2 contracts were already initialized when you deployed them, but you still
404404

405405
Complete these initialization steps:
406406

407-
#include_code initialize_l2_bridge /docs/examples/tutorials/token_bridge_contract/scripts/index.ts typescript
407+
#include_code initialize_l2_bridge /docs/examples/ts/token_bridge/index.ts typescript
408408

409409
This completes the setup. It's a lot of configuration, but you're dealing with four contracts across two chains.
410410

411411
### L1 → L2 Flow
412412

413413
Now for the main flow. Mint a CryptoPunk on L1, deposit it to Aztec, and claim it on Aztec. Put everything in the same script. To mint, call the L1 contract with `mint`, which will mint `tokenId = 0`:
414414

415-
#include_code mint_nft_l1 /docs/examples/tutorials/token_bridge_contract/scripts/index.ts typescript
415+
#include_code mint_nft_l1 /docs/examples/ts/token_bridge/index.ts typescript
416416

417417
To bridge, first approve the portal address to transfer the NFT, then transfer it by calling `depositToAztec`:
418418

419-
#include_code deposit_to_aztec /docs/examples/tutorials/token_bridge_contract/scripts/index.ts typescript
419+
#include_code deposit_to_aztec /docs/examples/ts/token_bridge/index.ts typescript
420420

421421
The `Inbox` contract will emit an important log: `MessageSent(inProgress, index, leaf, updatedRollingHash);`. This log provides the **leaf index** of the message in the [L1-L2 Message Tree](../../aztec-nr/framework-description/ethereum-aztec-messaging/index.md)—the location of the message in the tree that will appear on L2. You need this index, plus the secret, to correctly claim and decrypt the message.
422422

423423
Use viem to extract this information:
424424

425-
#include_code get_message_leaf_index /docs/examples/tutorials/token_bridge_contract/scripts/index.ts typescript
425+
#include_code get_message_leaf_index /docs/examples/ts/token_bridge/index.ts typescript
426426

427427
This extracts the logs from the deposit and retrieves the leaf index. You can now claim it on L2. However, for security reasons, at least 2 blocks must pass before a message can be claimed on L2. If you called `claim` on the L2 contract immediately, it would return "no message available".
428428

429429
Add a utility function to mine two blocks (it deploys a contract with a random salt):
430430

431-
#include_code mine_blocks /docs/examples/tutorials/token_bridge_contract/scripts/index.ts typescript
431+
#include_code mine_blocks /docs/examples/ts/token_bridge/index.ts typescript
432432

433433
Now claim the message on L2:
434434

435-
#include_code claim_on_l2 /docs/examples/tutorials/token_bridge_contract/scripts/index.ts typescript
435+
#include_code claim_on_l2 /docs/examples/ts/token_bridge/index.ts typescript
436436

437437
### L2 → L1 Flow
438438

439439
Great! You can expand the L2 contract to add features like NFT transfers. For now, exit the NFT on L2 and redeem it on L1. Mine two blocks because of `DelayedMutable`:
440440

441-
#include_code exit_from_l2 /docs/examples/tutorials/token_bridge_contract/scripts/index.ts typescript
441+
#include_code exit_from_l2 /docs/examples/ts/token_bridge/index.ts typescript
442442

443443
Just like in the L1 → L2 flow, you need to know what to claim on L1. Where in the message tree is the message you want to claim? Use the utility `computeL2ToL1MembershipWitness`, which provides the leaf and the sibling path of the message:
444444

445-
#include_code get_withdrawal_witness /docs/examples/tutorials/token_bridge_contract/scripts/index.ts typescript
445+
#include_code get_withdrawal_witness /docs/examples/ts/token_bridge/index.ts typescript
446446

447447
With this information, call the L1 contract and use the index and the sibling path to claim the L1 NFT:
448448

449-
#include_code withdraw_on_l1 /docs/examples/tutorials/token_bridge_contract/scripts/index.ts typescript
449+
#include_code withdraw_on_l1 /docs/examples/ts/token_bridge/index.ts typescript
450450

451451
You can now try the whole flow with:
452452

docs/examples/bootstrap.sh

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,39 @@ function compile {
1717
$REPO_ROOT/noir-projects/noir-contracts/bootstrap.sh compile "$@"
1818
}
1919

20+
function compile-solidity {
21+
echo_header "Compiling Solidity examples"
22+
local SOLIDITY_DIR="$REPO_ROOT/docs/examples/solidity"
23+
local OUTPUT_DIR="$REPO_ROOT/docs/target/solidity"
24+
25+
# Find all .sol files recursively
26+
local sol_files
27+
sol_files=$(find "$SOLIDITY_DIR" -name "*.sol" 2>/dev/null)
28+
if [ -z "$sol_files" ]; then
29+
echo_stderr "No Solidity files found in $SOLIDITY_DIR"
30+
return 0
31+
fi
32+
33+
mkdir -p "$OUTPUT_DIR"
34+
35+
# Compile using the local foundry.toml with proper remappings
36+
(
37+
cd "$SOLIDITY_DIR"
38+
for subdir in */; do
39+
if [ -d "$subdir" ] && ls "$subdir"/*.sol >/dev/null 2>&1; then
40+
local subdir_name=$(basename "$subdir")
41+
echo_stderr "Compiling $subdir_name..."
42+
forge build \
43+
--contracts "$subdir" \
44+
--out "$OUTPUT_DIR/$subdir_name" \
45+
--no-cache
46+
fi
47+
done
48+
)
49+
50+
echo_stderr "Solidity artifacts written to $OUTPUT_DIR"
51+
}
52+
2053
function validate-ts {
2154
echo_header "Validating TypeScript examples"
2255
(cd ts && ./bootstrap.sh "$@")
@@ -25,8 +58,12 @@ function validate-ts {
2558
case "$cmd" in
2659
"")
2760
compile
61+
compile-solidity
2862
validate-ts
2963
;;
64+
compile-solidity)
65+
compile-solidity
66+
;;
3067
*)
3168
default_cmd_handler "$@"
3269
;;
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[package]
2+
name = "nft"
3+
type = "contract"
4+
5+
[dependencies]
6+
aztec = { path = "../../../../noir-projects/aztec-nr/aztec" }

docs/examples/tutorials/token_bridge_contract/contracts/aztec/nft/src/main.nr renamed to docs/examples/contracts/nft/src/main.nr

File renamed without changes.

docs/examples/tutorials/token_bridge_contract/contracts/aztec/nft/src/nft.nr renamed to docs/examples/contracts/nft/src/nft.nr

File renamed without changes.

docs/examples/tutorials/token_bridge_contract/contracts/aztec/nft_bridge/Nargo.toml renamed to docs/examples/contracts/nft_bridge/Nargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@ name = "nft_bridge"
33
type = "contract"
44

55
[dependencies]
6-
aztec = { path = "../../../../../../../noir-projects/aztec-nr/aztec" }
6+
aztec = { path = "../../../../noir-projects/aztec-nr/aztec" }
77
NFTPunk = { path = "../nft" }

docs/examples/tutorials/token_bridge_contract/contracts/aztec/nft_bridge/src/main.nr renamed to docs/examples/contracts/nft_bridge/src/main.nr

File renamed without changes.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[profile.default]
2+
src = '.'
3+
out = 'out'
4+
libs = ['../../../l1-contracts/lib', '../../../l1-contracts/src']
5+
solc_version = '0.8.27'
6+
evm_version = 'prague'
7+
optimizer = true
8+
9+
remappings = [
10+
"@oz/=../../../l1-contracts/lib/openzeppelin-contracts/contracts/",
11+
"@aztec/=../../../l1-contracts/src/",
12+
"@aztec-blob-lib/=../../../l1-contracts/src/core/libraries/rollup/"
13+
]

0 commit comments

Comments
 (0)