Skip to content

Commit

Permalink
docs: update docs
Browse files Browse the repository at this point in the history
  • Loading branch information
LHerskind committed Apr 19, 2024
1 parent 486c9e5 commit bfc85fc
Show file tree
Hide file tree
Showing 15 changed files with 124 additions and 144 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,12 @@ Its arguments are `PXE` client and contract constructor arguments.

Additionally the `.send()` method can have a few optional arguments too, which are specified in an optional object:

- `portalContract?: EthAddress`: The L1 portal address to link the contract to. See the section on [Portals to learn more about them](../writing_contracts/portals/portals.md).
- `contractAddressSalt?: Fr`: A salt which is one of the inputs when computing a contract address of the contract to be deployed.
By default is set to a random value.
Set it, if you need a deterministic contract address (same functionality as Ethereum's `CREATE2` opcode).

```ts
const tx = ExampleContract.deploy(pxe).send({
portalContract: EthAddress.from("0x1234..."),
contractAddressSalt: new Fr(3n),
});
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,12 +139,9 @@ This proves that a contract exists in, ie had been deployed before or in, a cert
| contract_address_salt | Field | Unique identifier for the contract's address |
| function_tree_root | Field | Root of the contract's function tree |
| constructor_hash | Field | Hash of the contract's constructor |
| portal_contract_address | EthAddress | Ethereum address of the associated portal contract |
| block_number | u32 | Block number for proof verification |
| context | PrivateContext | Private context |

If there is no associated portal contract, you can use a zero Ethereum address:

```ts
new EthAddress(Buffer.alloc(EthAddress.SIZE_IN_BYTES));
```
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,7 @@ The call context contains information about the current call being made:

- This value is the address of the current context's contract address. This value will be the value of the current contract that is being executed except for when the current call is a delegate call (Warning: This is yet to be implemented). In this case the value will be that of the sending contract.

3. Portal Contract Address
- This value stores the current contract's linked [portal contract](../portals/portals.md) address. As a quick recap, this value is the value of the contracts related ethereum l1 contract address, and will be the recipient of any messages that are created by this contract.
4. Flags
3. Flags
- Furthermore there are a series of flags that are stored within the application context:
- is_delegate_call: Denotes whether the current call is a delegate call. If true, then the storage contract address will be the address of the sender.
- is_static_call: This will be set if and only if the current call is a static call. In a static call, state changing altering operations are not allowed.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ title: How to deploy a contract with a Portal
---

- Deploy to L1 using Viem, Foundry or your preferred tool;
- Deploy to L2 passing in the address of the L1 portal as an argument;
- Deploy to L2 and supply the L1 portal as an argument so you can store it in the contract;
```typescript
const deploymentTx = Contract.deploy(wallet, tokenPortalAddress).send();
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
title: Portals
---

A portal is the point of contact between L1 and a specific contract on Aztec. For applications such as token bridges, this is the point where the tokens are held on L1 while used in L2.
A portal is a point of contact between L1 and a contract on Aztec. For applications such as token bridges, this is the point where the tokens are held on L1 while used in L2.

As outlined in [Communication](../../../../learn/concepts/communication/cross_chain_calls.md), an Aztec L2 contract is linked to _ONE_ L1 address at time of deployment (specified by the developer). This L1 address is the only address that can send messages to that specific L2 contract, and the only address that can receive messages sent from the L2 contract to L1. Note, that a portal don't actually need to be a contract, it could be any address on L1. We say that an Aztec contract is attached to a portal.
As outlined in [Communication](../../../../learn/concepts/communication/cross_chain_calls.md), an Aztec L2 contract is linked to _ONE_ L1 address at time of deployment (specified by the developer). This L1 address is the only address that can send messages to that specific L2 contract, and the only address that can receive messages sent from the L2 contract to L1. Note, that a portal don't actually need to be a contract, it could be any address on L1.
2 changes: 1 addition & 1 deletion docs/docs/developers/debugging/aztecnr-errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ To address the error. find the line in the contract that is throwing the error a

This error occurs when you are trying to interact with a smart contract via an Private Execution Environment (PXE) that does not have the necessary information to execute a transaction.

To execute a transaction, the PXE needs to know the complete address of a contract, portal address (if portal is used) and contract artifacts.
To execute a transaction, the PXE needs to know the complete address of a contract and contract artifacts.

To address the error, add the contract to the PXE by calling [`pxe.addContracts(...)`](../../apis/pxe/interfaces/PXE.md#addcontracts).

Expand Down
13 changes: 7 additions & 6 deletions docs/docs/developers/tutorials/token_portal/minting_on_aztec.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,13 @@ The `claim_public` function enables anyone to consume the message on the user's
**What’s happening here?**

1. We first recompute the L1->L2 message content by calling `get_mint_public_content_hash()`. Note that the method does exactly the same as what the TokenPortal contract does in `depositToAztecPublic()` to create the content hash.
2. We then attempt to consume the L1->L2 message by passing the `msg_key`, the the content hash, and the "secret". Since we are depositing to Aztec publicly, this secret is public, anyone can know this and is usually 0.
- `context.consume_l1_to_l2_message()` takes in the content_hash and secret to recreate the original message. The L1 to L2 message consists of:
- Sender - who on L1 sent the message + chain ID of L1. The context variable knows the portal address on L1 and adds that
- Recipient - i.e. this aztec contract address which is consuming the message + the current version of the aztec rollup.
- The content - which is reconstructed in the `get_mint_public_content_hash()`
- Note that the `content_hash` requires `to`, `amount` and `canceller`. If a malicious user tries to mint tokens to their address by changing the to address, the content hash will be different to what the token portal had calculated on L1 and the `msg_Key` will also be different, thus preventing the L1->L2 message from being consumed. This is why we add these parameters into the content.
2. We then attempt to consume the L1->L2 message. Since we are depositing to Aztec publicly, all of the inputs are public.
- `context.consume_l1_to_l2_message()` takes in the few parameters:
- `content_hash`: The content - which is reconstructed in the `get_mint_public_content_hash()`
- `secret`: The secret used for consumption, often 0 for public messages
- `sender`: Who on L1 sent the message. Which should match the stored `portal_address` in our case as we only want to allow messages from a specific sender.
- `message_leaf_index`: The index in the message tree of the message.
- Note that the `content_hash` requires `to` and `amount`. If a malicious user tries to mint tokens to their address by changing the to address, the content hash will be different to what the token portal had calculated on L1 and thus not be in the tree, failing the consumption. This is why we add these parameters into the content.
3. Then we call `Token::at(storage.token.read()).mint_public()` to mint the tokens to the to address.

## Private flow
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ The `exit_to_l1_public` function enables anyone to withdraw their L2 tokens back

1. Like with our deposit function, we need to create the L2 to L1 message. The content is the _amount_ to burn, the recipient address, and who can execute the withdraw on the L1 portal on behalf of the user. It can be `0x0` for anyone, or a specified address.
2. `context.message_portal()` passes this content to the [kernel circuit](../../../learn/concepts/circuits/kernels/public_kernel.md) which creates the proof for the transaction. The kernel circuit then adds the sender (the L2 address of the bridge + version of aztec) and the recipient (the portal to the L2 address + the chain ID of L1) under the hood, to create the message which gets added as part of the transaction data published by the sequencer and is stored in the outbox for consumption.
2. The `context.message_portal()` takes the recipient and content as input, and will insert a message into the outbox. We set the recipient to be the portal address read from storage of the contract.
3. Finally, you also burn the tokens on L2! Note that it burning is done at the end to follow the check effects interaction pattern. Note that the caller has to first approve the bridge contract to burn tokens on its behalf. Refer to [burn_public function on the token contract](../writing_token_contract.md#burn_public). The nonce parameter refers to the approval message that the user creates - also refer to [authorizing token spends here](../writing_token_contract.md#authorizing-token-spends).
- We burn the tokens from the `msg_sender()`. Otherwise, a malicious user could burn someone else’s tokens and mint tokens on L1 to themselves. One could add another approval flow on the bridge but that might make it complex for other applications to call the bridge.

Expand Down Expand Up @@ -58,7 +59,7 @@ Before we can compile and use the contract, we need to add two additional functi

We need a function that lets us read the token value. Paste this into `main.nr`:

#include_code read_token /noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr rust
#include_code get_token /noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr rust

## Compile code

Expand Down
22 changes: 22 additions & 0 deletions docs/docs/misc/migration_notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,28 @@ keywords: [sandbox, cli, aztec, notes, migration, updating, upgrading]

Aztec is in full-speed development. Literally every version breaks compatibility with the previous ones. This page attempts to target errors and difficulties you might encounter when upgrading, and how to resolve them.

## [T.B.D]

## [Aztec.nr & js] Portal addresses
The deployment have been cleansed from the portal addresses as a immutable value passed in differently to other variables and instead should be implemented using usual storage by those who require it using the storage that matches the usecase - likely the shared storage to support private and public.

This means that you will likely add the portal as a constructor argument
```diff
- fn constructor(token: AztecAddress) {
- storage.token.write(token);
- }
+ fn constructor(token: AztecAddress, portal_address: EthAddress) {
+ storage.token.write(token);
+ storage.portal_address.initialize(portal_address);
+ }
```

And read it from storage whenever needed instead of from the context.
```diff
- context.this_portal_address(),
+ storage.portal_address.read_public(),
```

## 0.36.0

### [Aztec.nr] Oracles
Expand Down
6 changes: 1 addition & 5 deletions docs/docs/protocol-specs/contract-deployment/instances.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,16 +110,13 @@ fn deploy (
salt: Field,
contract_class_id: Field,
initialization_hash: Field,
portal_contract_address: Field,
public_keys_hash: Field,
universal_deploy?: boolean,
)
let contract_class_registerer: Contract = ContractClassRegisterer::at(CONTRACT_CLASS_REGISTERER_ADDRESS);

assert(nullifier_exists(silo(contract_class_id, contract_class_registerer.address)));

assert(is_valid_eth_address(portal_contract_address));

let deployer: Address = if universal_deploy { 0 } else { msg_sender };
let version: Field = 1;

Expand All @@ -129,13 +126,12 @@ fn deploy (
deployer,
contract_class_id,
initialization_hash,
portal_contract_address,
public_keys_hash
);

emit_nullifier(address);

emit_unencrypted_event(ContractInstanceDeployed::new(address, version, salt, contract_class_id, initialization_hash, portal_contract_address, public_keys_hash));
emit_unencrypted_event(ContractInstanceDeployed::new(address, version, salt, contract_class_id, initialization_hash, public_keys_hash));
```

> See [address](../addresses-and-keys/address.md) for `address_crh`.
Expand Down
9 changes: 5 additions & 4 deletions docs/docs/protocol-specs/l1-smart-contracts/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ The purpose of the L1 contracts are simple:

- Facilitate cross-chain communication such that L1 liquidity can be used on L2
- Act as a validating light node for L2 that every L1 node implicitly run
:::
:::

## Overview

Expand Down Expand Up @@ -188,8 +188,9 @@ Insertions require a L2 transaction, and it is then to be consumed and moved to

### Portals

When deploying a contract on L2, it is possible to specify its "portal" address.
This is an immutable variable, that can be used to constrain who the L2 contract expects messages from, and who it sends messages to.
Some contracts on L2 might wish to talk to contract on L1 - these recipients on L1 are called portals.

Often it is desired to constrain where messages are sent to and received from, which can be done by keeping the portal address in the storage of the L2 contract, such that it can be loaded on demand.

### Messages

Expand Down Expand Up @@ -488,7 +489,7 @@ Also, some of the conditions are repetitions of what we saw earlier from the [st

- For cost purposes, it can be useful to commit to the public inputs to just pass a single value into the circuit.
- Time constraints might change depending on the exact sequencer selection mechanism.
:::
:::

## Logical Execution

Expand Down
1 change: 0 additions & 1 deletion docs/docs/protocol-specs/public-vm/_nested-context.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ nestedExecutionEnvironment = ExecutionEnvironment {
sender: isDelegateCall ? context.sender : context.address,
address: M[addrOffset],
storageAddress: isDelegateCall ? context.storageAddress : M[addrOffset],
portal: callingContext.worldState.contracts[M[addrOffset]].portal,
feePerL1Gas: context.environment.feePerL1Gas,
feePerL2Gas: context.environment.feePerL2Gas,
feePerDaGas: context.environment.feePerDaGas,
Expand Down
1 change: 0 additions & 1 deletion docs/docs/protocol-specs/public-vm/avm-circuit.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,6 @@ AvmSessionInputs {
address: AztecAddress,
storageAddress: AztecAddress,
sender: AztecAddress,
portal: AztecAddress,
contractCallDepth: field,
isStaticCall: boolean,
isDelegateCall: boolean,
Expand Down
Loading

0 comments on commit bfc85fc

Please sign in to comment.