-
Notifications
You must be signed in to change notification settings - Fork 301
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(docs): Add uniswap back in as a reference and fix links (#7074)
Co-authored-by: josh crites <[email protected]>
- Loading branch information
1 parent
fbd3826
commit a4d1df6
Showing
13 changed files
with
192 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
6 changes: 6 additions & 0 deletions
6
docs/docs/reference/smart_contract_reference/examples/_category_.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"label": "Smart Contract Examples", | ||
"position": 0, | ||
"collapsible": true, | ||
"collapsed": true | ||
} |
6 changes: 6 additions & 0 deletions
6
docs/docs/reference/smart_contract_reference/examples/uniswap/_category_.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"label": "Uniswap Bridge", | ||
"position": 0, | ||
"collapsible": true, | ||
"collapsed": true | ||
} |
13 changes: 13 additions & 0 deletions
13
docs/docs/reference/smart_contract_reference/examples/uniswap/e2e_tests.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
--- | ||
title: e2e tests (TypeScript) | ||
sidebar_position: 3 | ||
--- | ||
|
||
## Private flow test | ||
|
||
#include_code uniswap_private yarn-project/end-to-end/src/shared/uniswap_l1_l2.ts typescript | ||
|
||
## Public flow test | ||
|
||
#include_code uniswap_public yarn-project/end-to-end/src/shared/uniswap_l1_l2.ts typescript | ||
|
31 changes: 31 additions & 0 deletions
31
docs/docs/reference/smart_contract_reference/examples/uniswap/index.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
--- | ||
title: Overview | ||
sidebar_position: 0 | ||
--- | ||
|
||
import Image from "@theme/IdealImage"; | ||
|
||
# Swap on L1 Uniswap from L2 | ||
|
||
This smart contract example allows someone with funds on L2 to be able to swap using L1 Uniswap and then get the swapped assets back to L2. In this example, L1 will refer to Ethereum and L2 will refer to Aztec. | ||
|
||
The flow will be: | ||
|
||
1. The user withdraws their “input” assets to L1 (i.e. burn them on L2 and create a L2 to L1 message to withdraw) | ||
2. We create an L2 → L1 message to swap on L1 | ||
3. On L1, the user gets their input tokens, consumes the swap message, and executes the swap | ||
4. The user deposits the “output” tokens to the output token portal so it can be deposited into L2 | ||
5. We will assume that token portals and token bridges for the input and output tokens must exist. These are what we built in the [token bridge tutorial](../../../../tutorials/contract_tutorials/advanced/token_bridge/0_setup.md). | ||
|
||
The execution of swap on L1 should be designed such that any 3rd party can execute the swap on behalf of the user. This helps maintain user privacy by not requiring links between L1 and L2 activity. | ||
|
||
This reference will cover: | ||
1. Uniswap Portal - a contract on L1 that talks to the input token portal to withdraw the assets, executes the swap, and deposits the swapped tokens back to L2 | ||
2. Uniswap L2 contract - a contract on L2 that creates the needed messages to perform the swap on L1 | ||
|
||
<Image img={require("/img/tutorials/uniswap_flow.png")} /> | ||
|
||
This diagram describes the private flow. | ||
|
||
This code works alongside a token portal that you can learn to build [in this tutorial](../../../../tutorials/contract_tutorials/advanced/token_bridge/0_setup.md). | ||
|
37 changes: 37 additions & 0 deletions
37
docs/docs/reference/smart_contract_reference/examples/uniswap/l1_contract.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
--- | ||
title: L1 contracts (EVM) | ||
sidebar_position: 2 | ||
--- | ||
|
||
This page goes over the code in the L1 contract for Uniswap, which works alongside a [token portal](../../../../tutorials/contract_tutorials/advanced/token_bridge/index.md). | ||
|
||
## Setup | ||
|
||
#include_code setup l1-contracts/test/portals/UniswapPortal.sol solidity | ||
|
||
## Public swap | ||
|
||
#include_code solidity_uniswap_swap_public l1-contracts/test/portals/UniswapPortal.sol solidity | ||
|
||
1. It fetches the input and output tokens we are swapping. The Uniswap portal only needs to know the portal addresses of the input and output as they store the underlying ERC20 token address. | ||
2. Consumes the `withdraw` message to get input tokens on L1 to itself. This is needed to execute the swap. | ||
|
||
Before it actually can swap, it checks if the provided swap parameters were what the user actually wanted by creating a message content hash (similar to what we did in the L2 contract) to ensure the right parameters are used. | ||
|
||
3. Executes the swap and receives the output funds to itself. | ||
|
||
The deadline by which the funds should be swapped is `block.timestamp` i.e. this block itself. This makes things atomic on the L1 side. | ||
|
||
4. The portal must deposit the output funds back to L2 using the output token’s portal. For this we first approve the token portal to move Uniswap funds, and then call the portal’s `depositToAztecPublic()` method to transfer funds to the portal and create a L1 → l2 message to mint the right amount of output tokens on L2. | ||
|
||
To incentivize the sequencer to pick up this message, we pass a fee to the deposit message. | ||
|
||
You can find the corresponding function on the [L2 contracts page](l2_contract.md#public-swap). | ||
|
||
## Private swap | ||
|
||
This works very similarly to the public flow. | ||
|
||
#include_code solidity_uniswap_swap_private l1-contracts/test/portals/UniswapPortal.sol solidity | ||
|
||
You can find the corresponding function on the [L2 contracts page](l2_contract.md#private-swap). |
89 changes: 89 additions & 0 deletions
89
docs/docs/reference/smart_contract_reference/examples/uniswap/l2_contract.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
--- | ||
title: L2 Contracts (Aztec) | ||
sidebar_position: 1 | ||
--- | ||
|
||
This page goes over the code in the L2 contract for Uniswap, which works alongside a [token bridge](../../../../tutorials/contract_tutorials/advanced/token_bridge/0_setup.md). | ||
|
||
## Main.nr | ||
|
||
### Setup and constructor | ||
|
||
#include_code uniswap_setup noir-projects/noir-contracts/contracts/uniswap_contract/src/main.nr rust | ||
We just need to store the portal address for the token that we want to swap. | ||
|
||
|
||
### Public swap | ||
|
||
#include_code swap_public noir-projects/noir-contracts/contracts/uniswap_contract/src/main.nr rust | ||
|
||
1. We check that `msg.sender()` has appropriate approval to call this on behalf of the sender by constructing an authwit message and checking if `from` has given the approval (read more about authwit [here](../../../../aztec/concepts/accounts/authwit.md)). | ||
2. We fetch the underlying aztec token that needs to be swapped. | ||
3. We transfer the user’s funds to the Uniswap contract. Like with Ethereum, the user must have provided approval to the Uniswap contract to do so. The user must provide the nonce they used in the approval for transfer, so that Uniswap can send it to the token contract, to prove it has appropriate approval. | ||
4. Funds are added to the Uniswap contract. | ||
5. Uniswap must exit the input tokens to L1. For this it has to approve the bridge to burn its tokens on its behalf and then actually exit the funds. We call the [`exit_to_l1_public()` method on the token bridge](../../../../tutorials/contract_tutorials/advanced/token_bridge/index.md). We use the public flow for exiting since we are operating on public state. | ||
6. It is not enough for us to simply emit a message to withdraw the funds. We also need to emit a message to display our swap intention. If we do not do this, there is nothing stopping a third party from calling the Uniswap portal with their own parameters and consuming our message. | ||
|
||
So the Uniswap portal (on L1) needs to know: | ||
|
||
- The token portals for the input and output token (to withdraw the input token to L1 and later deposit the output token to L2) | ||
- The amount of input tokens they want to swap | ||
- The Uniswap fee tier they want to use | ||
- The minimum output amount they can accept (for slippage protection) | ||
|
||
The Uniswap portal must first withdraw the input tokens, then check that the swap message exists in the outbox, execute the swap, and then call the output token to deposit the swapped tokens to L2. So the Uniswap portal must also be pass any parameters needed to complete the deposit of swapped tokens to L2. From the tutorial on building token bridges we know these are: | ||
|
||
- The address on L2 which must receive the output tokens (remember this is public flow) | ||
- The secret hash for consume the L1 to L2 message. Since this is the public flow the preimage doesn’t need to be a secret. | ||
|
||
You can find the corresponding function on the [L1 contracts page](l1_contract.md). | ||
|
||
### Private swap | ||
|
||
#include_code swap_private noir-projects/noir-contracts/contracts/uniswap_contract/src/main.nr rust | ||
|
||
This uses a util function `compute_swap_private_content_hash()` - find that [here](#utils) | ||
|
||
This flow works similarly to the public flow with a few notable changes: | ||
|
||
- Notice how in the `swap_private()`, user has to pass in `token` address which they didn't in the public flow? Since `swap_private()` is a private method, it can't read what token is publicly stored on the token bridge, so instead the user passes a token address, and `_assert_token_is_same()` checks that this user provided address is same as the one in storage. Note that because public functions are executed by the sequencer while private methods are executed locally, all public calls are always done after all private calls are done. So first the burn would happen and only later the sequencer asserts that the token is same. Note that the sequencer just sees a request to `execute_assert_token_is_same` and therefore has no context on what the appropriate private method was. If the assertion fails, then the kernel circuit will fail to create a proof and hence the transaction will be dropped. | ||
- In the public flow, the user calls `transfer_public()`. Here instead, the user calls `unshield()`. Why? The user can't directly transfer their private tokens (their notes) to the uniswap contract, because later the Uniswap contract has to approve the bridge to burn these notes and withdraw to L1. The authwit flow for the private domain requires a signature from the `sender`, which in this case would be the Uniswap contract. For the contract to sign, it would need a private key associated to it. But who would operate this key? | ||
- To work around this, the user can unshield their private tokens into Uniswap L2 contract. Unshielding would convert user's private notes to public balance. It is a private method on the token contract that reduces a user’s private balance and then calls a public method to increase the recipient’s (ie Uniswap) public balance. **Remember that first all private methods are executed and then later all public methods will be - so the Uniswap contract won’t have the funds until public execution begins.** | ||
- Now uniswap has public balance (like with the public flow). Hence, `swap_private()` calls the internal public method which approves the input token bridge to burn Uniswap’s tokens and calls `exit_to_l1_public` to create an L2 → L1 message to exit to L1. | ||
- Constructing the message content for swapping works exactly as the public flow except instead of specifying who would be the Aztec address that receives the swapped funds, we specify a secret hash (`secret_hash_for_redeeming_minted_notes`). Only those who know the preimage to the secret can later redeem the minted notes to themselves. | ||
|
||
### Approve the bridge to burn this contract's funds | ||
|
||
Both public and private swap functions call this function: | ||
|
||
#include_code authwit_uniswap_set noir-projects/noir-contracts/contracts/uniswap_contract/src/main.nr rust | ||
|
||
### Assertions | ||
|
||
#include_code assert_token_is_same noir-projects/noir-contracts/contracts/uniswap_contract/src/main.nr rust | ||
|
||
This is a simple function that asserts that the token passed in to the function is the one that the bridge is associated with. | ||
|
||
## Utils | ||
|
||
### Compute content hash for public | ||
|
||
#include_code uniswap_public_content_hash noir-projects/noir-contracts/contracts/uniswap_contract/src/util.nr rust | ||
|
||
This method computes the L2 to L1 message content hash for the public. To find out how it is consumed on L1, view the [L1 contracts page](./l1_contract.md) | ||
|
||
### Compute content hash for private | ||
|
||
#include_code compute_swap_private_content_hash noir-projects/noir-contracts/contracts/uniswap_contract/src/util.nr rust | ||
|
||
This method computes the L2 to L1 message content hash for the private. To find out how it is consumed on L1, view the [L1 contracts page](./l1_contract.md). | ||
|
||
## Redeeming assets | ||
|
||
So you emitted a message to withdraw input tokens to L1 and a message to swap. Then you or someone on your behalf can swap on L1 and emit a message to deposit swapped assets to L2. | ||
|
||
You still need to "claim" these swapped funds on L2. | ||
|
||
In the public flow, you can call [`claim_public()`](../../../../tutorials/contract_tutorials/advanced/token_bridge/2_minting_on_aztec.md) on the output token bridge which consumes the deposit message and mints your assets. | ||
|
||
In the private flow, you can choose to leak your secret for L1 → L2 message consumption to let someone mint the notes on L2 (by calling [`claim_private()`](../../../../tutorials/contract_tutorials/advanced/token_bridge/2_minting_on_aztec.md) on the output token bridge) and then you can later redeem these notes to yourself by presenting the preimage to `secret_hash_for_redeeming_minted_notes` and calling the `redeem_shield()` method on the token contract. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
docs/docs/reference/smart_contract_reference/history_lib_reference.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
docs/docs/reference/smart_contract_reference/portals/_category_.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
{ | ||
"label": "Portals", | ||
"position": 3, | ||
"position": 4, | ||
"collapsible": true, | ||
"collapsed": true | ||
} |
2 changes: 1 addition & 1 deletion
2
docs/docs/reference/smart_contract_reference/storage/_category_.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
{ | ||
"position": 0, | ||
"position": 1, | ||
"collapsible": true, | ||
"collapsed": true, | ||
"label": "Storage" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters