Skip to content

Commit 69ac132

Browse files
author
Esau
committed
fix
fix fix abc abc abc abc abc fix add comment abc
1 parent 1e79819 commit 69ac132

File tree

4 files changed

+104
-84
lines changed

4 files changed

+104
-84
lines changed

docs/examples/solidity/foundry.toml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,8 @@ solc_version = '0.8.27'
66
evm_version = 'prague'
77
optimizer = true
88

9-
# Match l1-contracts remappings exactly
109
remappings = [
1110
"@oz/=../../../l1-contracts/lib/openzeppelin-contracts/contracts/",
1211
"@aztec/=../../../l1-contracts/src/",
13-
"@openzeppelin/contracts/=../../../l1-contracts/lib/openzeppelin-contracts/contracts/",
14-
"@aztec-blob-lib/=../../../l1-contracts/src/mock/libraries/"
12+
"@aztec-blob-lib/=../../../l1-contracts/src/core/libraries/rollup/"
1513
]

docs/examples/solidity/nft_bridge/NFTPortal.sol

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {IOutbox} from "@aztec/core/interfaces/messagebridge/IOutbox.sol";
99
import {IRollup} from "@aztec/core/interfaces/IRollup.sol";
1010
import {DataStructures} from "@aztec/core/libraries/DataStructures.sol";
1111
import {Hash} from "@aztec/core/libraries/crypto/Hash.sol";
12+
import {Epoch} from "@aztec/core/libraries/TimeLib.sol";
1213

1314
contract NFTPortal {
1415
IRegistry public registry;
@@ -50,7 +51,7 @@ contract NFTPortal {
5051
// Unlock NFT after L2 burn
5152
function withdraw(
5253
uint256 tokenId,
53-
uint256 l2BlockNumber,
54+
Epoch epoch,
5455
uint256 leafIndex,
5556
bytes32[] calldata path
5657
) external {
@@ -61,7 +62,7 @@ contract NFTPortal {
6162
content: Hash.sha256ToField(abi.encodePacked(tokenId, msg.sender))
6263
});
6364

64-
outbox.consume(message, l2BlockNumber, leafIndex, path);
65+
outbox.consume(message, epoch, leafIndex, path);
6566

6667
// Unlock NFT
6768
nftContract.transferFrom(address(this), msg.sender, tokenId);

docs/examples/ts/token_bridge/config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,4 @@ dependencies:
1616
- "@aztec/stdlib"
1717
- "@aztec/foundation"
1818
- "@aztec/ethereum"
19-
- "npm:viem@npm:@aztec/viem@2.38.2"
19+
- "npm:@aztec/viem@2.38.2"
Lines changed: 99 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// docs:start:setup
2-
import { privateKeyToAccount } from "viem/accounts";
3-
import { decodeEventLog, getContract, pad } from "viem";
4-
import { foundry } from "viem/chains";
2+
import { decodeEventLog, pad } from "@aztec/viem";
3+
import { foundry } from "@aztec/viem/chains";
54
import { AztecAddress, EthAddress } from "@aztec/aztec.js/addresses";
65
import { Fr } from "@aztec/aztec.js/fields";
76
import { createAztecNodeClient } from "@aztec/aztec.js/node";
@@ -13,40 +12,41 @@ import { TestWallet } from "@aztec/test-wallet/server";
1312
import { getInitialTestAccountsData } from "@aztec/accounts/testing";
1413
import { createExtendedL1Client } from "@aztec/ethereum/client";
1514
import { deployL1Contract } from "@aztec/ethereum/deploy-l1-contract";
15+
import { CheckpointNumber } from "@aztec/foundation/branded-types";
16+
import { RollupContract } from "@aztec/ethereum/contracts";
1617
import SimpleNFT from "../../../target/solidity/nft_bridge/SimpleNFT.sol/SimpleNFT.json" with { type: "json" };
1718
import NFTPortal from "../../../target/solidity/nft_bridge/NFTPortal.sol/NFTPortal.json" with { type: "json" };
1819
import { NFTPunkContract } from "./artifacts/NFTPunk.js";
1920
import { NFTBridgeContract } from "./artifacts/NFTBridge.js";
2021

21-
// Setup L1 client using anvil's 1st account which should have a ton of ETH already
22-
const l1Account = privateKeyToAccount(
23-
"0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
24-
);
25-
const l1Client = createExtendedL1Client(
26-
["http://localhost:8545"],
27-
l1Account,
28-
foundry
29-
);
22+
// Setup L1 client using anvil's default mnemonic (same as e2e tests)
23+
const MNEMONIC = "test test test test test test test test test test test junk";
24+
const l1Client = createExtendedL1Client(["http://localhost:8545"], MNEMONIC);
25+
const ownerEthAddress = l1Client.account.address;
3026

3127
// Setup L2 using Aztec's local network and one of its initial accounts
32-
console.log("🔮 Setting up L2...\n");
28+
console.log("Setting up L2...\n");
3329
const node = createAztecNodeClient("http://localhost:8080");
3430
const aztecWallet = await TestWallet.create(node);
3531
const [accData] = await getInitialTestAccountsData();
3632
const account = await aztecWallet.createSchnorrAccount(
3733
accData.secret,
3834
accData.salt
3935
);
40-
console.log(`Account: ${account.address.toString()}\n`);
36+
console.log(`Account: ${account.address.toString()}\n`);
4137

4238
// Get node info
4339
const nodeInfo = await node.getNodeInfo();
4440
const registryAddress = nodeInfo.l1ContractAddresses.registryAddress.toString();
4541
const inboxAddress = nodeInfo.l1ContractAddresses.inboxAddress.toString();
42+
const rollupAddress = nodeInfo.l1ContractAddresses.rollupAddress.toString();
43+
44+
// Create rollup contract instance for querying epoch information
45+
const rollup = new RollupContract(l1Client, rollupAddress);
4646
// docs:end:setup
4747

4848
// docs:start:deploy_l1_contracts
49-
console.log("📦 Deploying L1 contracts...\n");
49+
console.log("Deploying L1 contracts...\n");
5050

5151
const { address: nftAddress } = await deployL1Contract(
5252
l1Client,
@@ -60,12 +60,12 @@ const { address: portalAddress } = await deployL1Contract(
6060
NFTPortal.bytecode.object as `0x${string}`
6161
);
6262

63-
console.log(`SimpleNFT: ${nftAddress}`);
64-
console.log(`NFTPortal: ${portalAddress}\n`);
63+
console.log(`SimpleNFT: ${nftAddress}`);
64+
console.log(`NFTPortal: ${portalAddress}\n`);
6565
// docs:end:deploy_l1_contracts
6666

6767
// docs:start:deploy_l2_contracts
68-
console.log("📦 Deploying L2 contracts...\n");
68+
console.log("Deploying L2 contracts...\n");
6969

7070
const l2Nft = await NFTPunkContract.deploy(aztecWallet, account.address)
7171
.send({ from: account.address })
@@ -75,36 +75,28 @@ const l2Bridge = await NFTBridgeContract.deploy(aztecWallet, l2Nft.address)
7575
.send({ from: account.address })
7676
.deployed();
7777

78-
console.log(`L2 NFT: ${l2Nft.address.toString()}`);
79-
console.log(`L2 Bridge: ${l2Bridge.address.toString()}\n`);
78+
console.log(`L2 NFT: ${l2Nft.address.toString()}`);
79+
console.log(`L2 Bridge: ${l2Bridge.address.toString()}\n`);
8080
// docs:end:deploy_l2_contracts
8181

8282
// docs:start:initialize_portal
83-
console.log("🔧 Initializing portal...");
83+
console.log("Initializing portal...");
8484

85-
const nftContract = getContract({
86-
address: nftAddress.toString() as `0x${string}`,
87-
abi: SimpleNFT.abi,
88-
client: l1Client,
89-
});
90-
const portalContract = getContract({
85+
// Initialize the portal contract
86+
// @ts-expect-error - viem type inference doesn't work with JSON-imported ABIs
87+
const initHash = await l1Client.writeContract({
9188
address: portalAddress.toString() as `0x${string}`,
9289
abi: NFTPortal.abi,
93-
client: l1Client,
90+
functionName: "initialize",
91+
args: [registryAddress, nftAddress.toString(), l2Bridge.address.toString()],
9492
});
93+
await l1Client.waitForTransactionReceipt({ hash: initHash });
9594

96-
const hash = await portalContract.write.initialize([
97-
registryAddress as `0x${string}`,
98-
nftAddress.toString() as `0x${string}`,
99-
l2Bridge.address.toString() as `0x${string}`,
100-
]);
101-
await l1Client.waitForTransactionReceipt({ hash });
102-
103-
console.log("✅ Portal initialized\n");
95+
console.log("Portal initialized\n");
10496
// docs:end:initialize_portal
10597

10698
// docs:start:initialize_l2_bridge
107-
console.log("🔧 Setting up L2 bridge...");
99+
console.log("Setting up L2 bridge...");
108100

109101
await l2Bridge.methods
110102
.set_portal(EthAddress.fromString(portalAddress.toString()))
@@ -116,37 +108,51 @@ await l2Nft.methods
116108
.send({ from: account.address })
117109
.wait();
118110

119-
console.log("Bridge configured\n");
111+
console.log("Bridge configured\n");
120112
// docs:end:initialize_l2_bridge
121113

122114
// docs:start:mint_nft_l1
123-
console.log("🎨 Minting NFT on L1...");
115+
console.log("Minting NFT on L1...");
124116

125-
const mintHash = await nftContract.write.mint([l1Account.address]);
117+
// @ts-expect-error - viem type inference doesn't work with JSON-imported ABIs
118+
const mintHash = await l1Client.writeContract({
119+
address: nftAddress.toString() as `0x${string}`,
120+
abi: SimpleNFT.abi,
121+
functionName: "mint",
122+
args: [ownerEthAddress],
123+
});
126124
await l1Client.waitForTransactionReceipt({ hash: mintHash });
127125

128126
// no need to parse logs, this will be tokenId 0 since it's a fresh contract
129127
const tokenId = 0n;
130128

131-
console.log(`Minted tokenId: ${tokenId}\n`);
129+
console.log(`Minted tokenId: ${tokenId}\n`);
132130
// docs:end:mint_nft_l1
133131

134132
// docs:start:deposit_to_aztec
135-
console.log("🌉 Depositing NFT to Aztec...");
133+
console.log("Depositing NFT to Aztec...");
136134

137135
const secret = Fr.random();
138136
const secretHash = await computeSecretHash(secret);
139137

140-
const approveHash = await nftContract.write.approve([
141-
portalAddress.toString() as `0x${string}`,
142-
tokenId,
143-
]);
138+
// Approve portal to transfer the NFT
139+
// @ts-expect-error - viem type inference doesn't work with JSON-imported ABIs
140+
const approveHash = await l1Client.writeContract({
141+
address: nftAddress.toString() as `0x${string}`,
142+
abi: SimpleNFT.abi,
143+
functionName: "approve",
144+
args: [portalAddress.toString(), tokenId],
145+
});
144146
await l1Client.waitForTransactionReceipt({ hash: approveHash });
145147

146-
const depositHash = await portalContract.write.depositToAztec([
147-
tokenId,
148-
pad(secretHash.toString() as `0x${string}`, { dir: "left", size: 32 }),
149-
]);
148+
// Deposit to Aztec
149+
// @ts-expect-error - viem type inference doesn't work with JSON-imported ABIs
150+
const depositHash = await l1Client.writeContract({
151+
address: portalAddress.toString() as `0x${string}`,
152+
abi: NFTPortal.abi,
153+
functionName: "depositToAztec",
154+
args: [tokenId, pad(secretHash.toString() as `0x${string}`, { dir: "left", size: 32 })],
155+
});
150156
const depositReceipt = await l1Client.waitForTransactionReceipt({
151157
hash: depositHash,
152158
});
@@ -167,22 +173,24 @@ const INBOX_ABI = [
167173
] as const;
168174

169175
// Find and decode the MessageSent event from the Inbox contract
170-
const messageSentLog = depositReceipt.logs
176+
const messageSentLogs = depositReceipt.logs
171177
.filter((log) => log.address.toLowerCase() === inboxAddress.toLowerCase())
172-
.map((log) => {
178+
.map((log: any) => {
173179
try {
174-
return decodeEventLog({
180+
const decoded = decodeEventLog({
175181
abi: INBOX_ABI,
176182
data: log.data,
177183
topics: log.topics,
178184
});
185+
return { log, decoded };
179186
} catch {
187+
// Not a decodable event from this ABI
180188
return null;
181189
}
182190
})
183-
.find((decoded) => decoded?.eventName === "MessageSent");
191+
.filter((item): item is { log: any; decoded: any } => item !== null && (item.decoded as any).eventName === "MessageSent");
184192

185-
const messageLeafIndex = new Fr(messageSentLog!.args.index);
193+
const messageLeafIndex = new Fr(messageSentLogs[0].decoded.args.index);
186194
// docs:end:get_message_leaf_index
187195

188196
// docs:start:mine_blocks
@@ -201,44 +209,44 @@ async function mine2Blocks(aztecWallet: TestWallet, accountAddress: AztecAddress
201209
await mine2Blocks(aztecWallet, account.address);
202210

203211
// Check notes before claiming (should be 0)
204-
console.log("📝 Checking notes before claim...");
212+
console.log("Checking notes before claim...");
205213
const notesBefore = await l2Nft.methods
206214
.notes_of(account.address)
207215
.simulate({ from: account.address });
208216
console.log(` Notes count: ${notesBefore}`);
209217

210-
console.log("🎯 Claiming NFT on L2...");
218+
console.log("Claiming NFT on L2...");
211219
await l2Bridge.methods
212220
.claim(account.address, new Fr(Number(tokenId)), secret, messageLeafIndex)
213221
.send({ from: account.address })
214222
.wait();
215-
console.log("NFT claimed on L2\n");
223+
console.log("NFT claimed on L2\n");
216224

217225
// Check notes after claiming (should be 1)
218-
console.log("📝 Checking notes after claim...");
226+
console.log("Checking notes after claim...");
219227
const notesAfterClaim = await l2Nft.methods
220228
.notes_of(account.address)
221229
.simulate({ from: account.address });
222230
console.log(` Notes count: ${notesAfterClaim}\n`);
223231
// docs:end:claim_on_l2
224232

225233
// docs:start:exit_from_l2
226-
// L2 L1 flow
227-
console.log("🚪 Exiting NFT from L2...");
234+
// L2 -> L1 flow
235+
console.log("Exiting NFT from L2...");
228236
// Mine blocks, not necessary on devnet, but must wait for 2 blocks
229237
await mine2Blocks(aztecWallet, account.address);
230238

231-
const recipientEthAddress = EthAddress.fromString(l1Account.address);
239+
const recipientEthAddress = EthAddress.fromString(ownerEthAddress);
232240

233241
const exitReceipt = await l2Bridge.methods
234242
.exit(new Fr(Number(tokenId)), recipientEthAddress)
235243
.send({ from: account.address })
236244
.wait();
237245

238-
console.log(`Exit message sent (block: ${exitReceipt.blockNumber})\n`);
246+
console.log(`Exit message sent (block: ${exitReceipt.blockNumber})\n`);
239247

240248
// Check notes after burning (should be 0 again)
241-
console.log("📝 Checking notes after burn...");
249+
console.log("Checking notes after burn...");
242250
const notesAfterBurn = await l2Nft.methods
243251
.notes_of(account.address)
244252
.simulate({ from: account.address });
@@ -258,9 +266,14 @@ const content = sha256ToField([
258266
]);
259267

260268
// Get rollup version from the portal contract (it stores it during initialize)
261-
const version = await portalContract.read.rollupVersion();
269+
// @ts-expect-error - viem type inference doesn't work with JSON-imported ABIs
270+
const version = (await l1Client.readContract({
271+
address: portalAddress.toString() as `0x${string}`,
272+
abi: NFTPortal.abi,
273+
functionName: "rollupVersion",
274+
})) as bigint;
262275

263-
// Compute the L2L1 message hash
276+
// Compute the L2->L1 message hash
264277
const msgLeaf = computeL2ToL1MessageHash({
265278
l2Sender: l2Bridge.address,
266279
l1Recipient: EthAddress.fromString(portalAddress.toString()),
@@ -271,7 +284,7 @@ const msgLeaf = computeL2ToL1MessageHash({
271284

272285
// Wait for the block to be proven before withdrawing
273286
// Waiting for the block to be proven is not necessary on the local network, but it is necessary on devnet
274-
console.log("Waiting for block to be proven...");
287+
console.log("Waiting for block to be proven...");
275288
console.log(` Exit block number: ${exitReceipt.blockNumber}`);
276289

277290
let provenBlockNumber = await node.getProvenBlockNumber();
@@ -285,12 +298,19 @@ while (provenBlockNumber < exitReceipt.blockNumber!) {
285298
provenBlockNumber = await node.getProvenBlockNumber();
286299
}
287300

288-
console.log("Block proven!\n");
301+
console.log("Block proven!\n");
289302

290-
// Compute the membership witness using the message hash
303+
// Get the epoch for the exit block's checkpoint
304+
// In Aztec, checkpoint number equals block number (1:1 mapping)
305+
const epoch = await rollup.getEpochNumberForCheckpoint(
306+
CheckpointNumber.fromBlockNumber(exitReceipt.blockNumber!)
307+
);
308+
console.log(` Epoch for block ${exitReceipt.blockNumber}: ${epoch}`);
309+
310+
// Compute the membership witness using the message hash and epoch
291311
const witness = await computeL2ToL1MembershipWitness(
292312
node,
293-
exitReceipt.blockNumber!,
313+
epoch,
294314
msgLeaf
295315
);
296316
const siblingPathHex = witness!.siblingPath
@@ -299,13 +319,14 @@ const siblingPathHex = witness!.siblingPath
299319
// docs:end:get_withdrawal_witness
300320

301321
// docs:start:withdraw_on_l1
302-
console.log("💰 Withdrawing NFT on L1...");
303-
const withdrawHash = await portalContract.write.withdraw([
304-
tokenId,
305-
BigInt(exitReceipt.blockNumber!),
306-
BigInt(witness!.leafIndex),
307-
siblingPathHex,
308-
]);
322+
console.log("Withdrawing NFT on L1...");
323+
// @ts-expect-error - viem type inference doesn't work with JSON-imported ABIs
324+
const withdrawHash = await l1Client.writeContract({
325+
address: portalAddress.toString() as `0x${string}`,
326+
abi: NFTPortal.abi,
327+
functionName: "withdraw",
328+
args: [tokenId, BigInt(epoch), BigInt(witness!.leafIndex), siblingPathHex],
329+
});
309330
await l1Client.waitForTransactionReceipt({ hash: withdrawHash });
310-
console.log("NFT withdrawn to L1\n");
331+
console.log("NFT withdrawn to L1\n");
311332
// docs:end:withdraw_on_l1

0 commit comments

Comments
 (0)