Skip to content

Commit

Permalink
Docs audit (#85)
Browse files Browse the repository at this point in the history
* outline of new pages

* block building interface

* add some more detail

* Integratoooooor!

* Finish off first run

* Fix spelling, adjust sidebar naming

* Fix build

* Attends to George's feedback, with gratitude

* furter tee info from dmarzzz discussion

* update forge page, fix now-broken links

* Still keeping up with the Borreguero's

* Fix broken faucet link

* More logical directory organisation, clean up pages, adjust suave-std tutorial

* Attend to dmarzzz feedback

* remove stale pages

* Cleaning up, making clearer

* Final feedback on the audit from dmarzzz

---------

Co-authored-by: dmarzzz <[email protected]>
  • Loading branch information
andytudhope and dmarzzz authored Jan 17, 2024
1 parent e46271a commit f884e2e
Show file tree
Hide file tree
Showing 13 changed files with 99 additions and 137 deletions.
8 changes: 5 additions & 3 deletions docs/concepts/block-building.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ function sessionExample(bytes memory subTxn, bytes memory subTxn2) public payabl

In this example, a new builder session is created, and multiple transactions are simulated with varying conditions in order to illustrate how you might approach building blocks with SUAVE.

## Conceptual Explanation
## Interface

SUAVE exposes several precompiles to help you with transaction simulation and block construction.

Expand All @@ -44,7 +44,7 @@ If your SUAPP is intended to produce blocks, be they partial or full, you'll fir
function newBuilder() internal view returns (string memory)
```

This function starts a new builder instance within a Kettle. The basic idea is that session ids (the `string` returned by the `newBuilder()` precompile) provide programmatic control when building blocks, one outcome of which is simulating transactions more efficiently. Opening a session enables you to build block iteratively, rather than having to re-run all your simulations each time you receive a new transaction or bundle.
This function starts a new builder instance within a Kettle. The basic idea is that session ids (the `string` returned by the `newBuilder()` precompile) provide programmatic control when building blocks, one outcome of which is simulating transactions more efficiently. Opening a session enables you to build blocks iteratively, rather than having to re-run all your simulations each time you receive a new transaction or bundle.

:::info

Expand All @@ -71,5 +71,7 @@ All of these functions utilize the SUAVE Execution Namespace. To understand more

## Bundles

Bundles are one or more transactions that are grouped together and executed in the order they are provided and are the core unit of block building. If you're unfamiliar with bundles, and want to learn more, you can read [this document](https://docs.flashbots.net/flashbots-auction/advanced/understanding-bundles).
Bundles are one or more transactions that are grouped together and executed in the order they are provided and are the core unit of block building. If you're unfamiliar with bundles, and want to learn more, you can read [this document](https://docs.flashbots.net/flashbots-auction/advanced/understanding-bundles).

To see how to handle bundles in your SUAPP, check out the [`suave-std` repo](https://github.com/flashbots/suave-std/pull/28).

36 changes: 15 additions & 21 deletions docs/concepts/confidential-computation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,43 +3,37 @@ title: Confidential Computation
description: How to understand confidential computation on SUAVE and use it to yur advantage.
---

import List from '@site/src/components/List/List.tsx';

Confidential computation enables you to handle orderflow privately and securely.

In SUAVE, we achieve this with [Kettles](/technical/specs/rigil/kettle#confidential-computation) performing compute offchain, but according to smart contracts written onchain. In this way, offchain compute is not constrained by chain consensus. The Kettles will eventually run in [TEEs](https://www.youtube.com/watch?v=ek-bu4aoh0A), which provide both enhanced privacy (no-one, not even the host OS, can see unencrypted data) and integrity (you can be sure the correct code, and only that code, is running at all times).

## How It Works
In SUAVE, we achieve this with [Kettles](/technical/specs/rigil/kettle#confidential-computation) performing compute offchain, but according to smart contracts written onchain. In this way, offchain compute is not constrained by chain consensus. The Kettles will eventually run in [TEEs](https://www.youtube.com/watch?v=ek-bu4aoh0A), which provide both **enhanced privacy** (no-one, not even the host OS, can see unencrypted data) and **integrity** (you can be sure the correct code, and only that code, is running at all times).

:::info

For practical examples of how Confidential Compute Requests (CCRs) work, please follow [**this tutorial**](/tutorials/confidential-compute-requests). The below will explain CCRs conceptually, without code.

:::

<List>

**Starting Point**: A user sends "Confidential Compute Request" using `eth_sendRawTransaction`, which is received by the JSON RPC.

<div>

**MEVM Execution**: Upon receiving the request, the JSON RPC triggers the MEVM (Modified Ethereum Virtual Machine) to run. MEVM execution can use multiple APIs depending on the context, with two possible paths:

<List>
## Interface

**Request to an External Domain**: The MEVM can make API requests to external domains: i.e. if you're running an Ethereum node, it can fetch state from there for simulations etc., or if the SUAPP uses the `doHttpRequest()` precompile, it can fetch arbitrary information required for the offchain compute.
SUAVE exposes several precompiles to help you with confidential computation. The first is a simple check, often used in `require` statements in smart contracts:

**Request to the Confidential Datastore**: The MEVM can make API requests directly to the "Confidential Datastore" to fetch or store data.
```solidity
function isConfidential() internal view returns (bool b)
```

</List>
If whoever calls a function in the contract has passed in confidential inputs to be computed offchain, then those inputs can be accessed by the MEVM using:

</div>
```solidity
function confidentialInputs() internal view returns (bytes memory)
```

**Broadcast results**: Eventually, after processing the request the MEVM can take the results and, depending on the SUAPP's logic, send a SUAVE transaction, which is a transaction object that contains the result of the CCR in its calldata (and the signature of the Kettle which computed said result), which enables other users or contracts to take action.
Once the MEVM has the confidential inputs, there is any number of things you could tell it to do with them. For instance, in the [Private OFA Suapp](https://github.com/flashbots/suapp-examples/tree/main/examples/app-ofa-private) we'll look at in greater detail below, we use the below precompile to extract any information about a transaction that the user has agreed to share in order for it to be included timeously in a block on Ethereum L1, thereby replicating MEV-Share in a smart contract on SUAVE:

**Transaction Hash Output**: A transaction hash for the Suave transaction above is produced and returned to the request's originator, just like Ethereum.
```solidity
function extractHint(bytes memory bundleData) internal view returns (bytes memory)
```

</List>
You can also consult [our technical specs](/technical/specs/rigil/kettle#confidential-computation) for further information about confidential computation if required.

### Computing over Confidential Data

Expand Down
6 changes: 3 additions & 3 deletions docs/concepts/confidential-data-storage.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ description: How to leverage confidential data to your advantage when building o

import List from '@site/src/components/List/List.tsx';

## Data Records

Confidential storage works with opaque identifiers, which are generated by Kettles when data is put in storage during offchain/confidential computation. These identifiers are part of an object we call a `DataRecord`, which holds a reference to the data, its ID, who can store and retrieve it, and a few other pieces of metadata.

## Interface

This is what these DataRecords look like in the [`suave-std` library](https://github.com/flashbots/suave-std/blob/main/src/suavelib/Suave.sol):

```solidity
Expand All @@ -26,7 +26,7 @@ This is what these DataRecords look like in the [`suave-std` library](https://gi

## Practical Example

Consider the same [Private OFA Suapp](https://github.com/flashbots/suapp-examples/blob/main/examples/app-ofa-private/ofa-private.sol) from the previous tutorial. The OFA contract needs to accept user transactions, store them, and emit a hint that searchers can use. It then needs to accept backruns from searchers and match those with the user transactions in storage: a task it achieves by means of the `recordId`.
Consider the same [Private OFA Suapp](https://github.com/flashbots/suapp-examples/blob/main/examples/app-ofa-private/ofa-private.sol) from the previous page. The OFA contract needs to accept user transactions, store them, and emit a hint that searchers can use. It then needs to accept backruns from searchers and match those with the user transactions in storage: a task it achieves by means of the `recordId`.

The end-to-end flow looks like this:

Expand Down
30 changes: 10 additions & 20 deletions docs/concepts/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,20 @@ keywords:
- concepts
---

import List from '@site/src/components/List/List.tsx';
import DocCardList from '@theme/DocCardList';

SUAVE gives you, an application developer, a way to:
Each of the pages in this section describes one of the ways in which SUAVE extends Solidity and gives you, a MEV application developer, unique advantages.

<List>
<DocCardList />

Define private compute
In brief, SUAVE enables you to:

Store private data
- 🛠 Build blocks on other chains

Build blocks on other chains
- 🧑‍💻 Define private compute

<div>
- 🕵️‍♀️ Store private data

Interface with many different MEV components, meaning that you can

<List>

Plug into existing MEV infra: i.e sending bundles to block builders, relays, validators or sequencers

Build totally new MEV infra: i.e. create unique SUAPPs on SUAVE

</List>

</div>

</List>
- 🧩 Interface with many different MEV components, meaning that you can
- ⚡ Plug into existing MEV infra: i.e sending bundles to block builders, relays, validators or sequencers
- 🤖 Build totally new MEV infra: i.e. create unique SUAPPs on SUAVE
4 changes: 2 additions & 2 deletions docs/concepts/mev-supplychain-interface.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ At a first approximation, the MEV supply chain looks like this:

The point of this section has been to illustrate that SUAPPs can interact with any of these components.

### Off-SUAVE interaction
### Off-SUAVE interface

```solidity
function submitBundleJsonRPC(string memory url, string memory method, bytes memory params) internal view returns (bytes memory)
Expand Down Expand Up @@ -45,7 +45,7 @@ function submitBundle(string memory builderUrl, bytes memory bundleData) interna
}
```

### On SUAVE interaction
### On-SUAVE interface

```solidity
function confidentialStore(DataId dataId, string memory key, bytes memory value) internal view
Expand Down
2 changes: 1 addition & 1 deletion docs/resources/forge.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ In order to make interacting with these precompiles easier, we maintain a reposi
The easiest way to start creating your own contracts with Forge is to clone the [Suapp Examples repo](https://github.com/flashbots/suapp-examples/), as it comes with `suave-std` already set up as a submodule, as well as a series of examples that use both Forge and the Golang SDK.

```bash
git clone [email protected]:flashbots/suave-std.git && cd suapp-examples
git clone [email protected]:flashbots/suapp-examples.git && cd suapp-examples
```

```bash
Expand Down
8 changes: 5 additions & 3 deletions docs/tutorials/build-suapps.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ cd src/ && bun link

1. Confidential Compute Requests on SUAVE do not work with wallets that implement the EIP-1193 Javascript API. Therefore, we use the unsafe `eth_sign` method to sign CCRs, which does work, but requires that you enable this functionality in wallets like MetaMask.
1. To do so in MetaMask, go to "Settings" -> "Advanced" -> scroll to bottom -> switch Eth_sign requests on.
2. Both templates assume that you are running SUAVE locally.
3. No tests are included for the contracts, as it is not trivial to test new precompiles and different transaction types (i.e. CCRs) in `forge` at this time.
2. Both templates below assume that you are running SUAVE locally.
3. No tests are included for the contracts at this time.

## Typescript Template

Expand Down Expand Up @@ -72,7 +72,9 @@ This template uses the same MEV-Share example contract we worked with using the

## Next Template

This template comes with a more extensive frontend framework, which uses Next (in typescript) and therefore depends on React. You can get it running by first cloning the repo and installing its dependencies. Make sure you have previously built and symlinked suave-viem for this to work:
This template comes with a more extensive frontend framework, which uses Next (in typescript) and therefore depends on React. You can get it running by first cloning the repo and installing its dependencies.

Make sure you have previously built and symlinked suave-viem for this to work:

```bash
git clone [email protected]:andytudhope/build-a-suapp-next-ts.git \
Expand Down
8 changes: 5 additions & 3 deletions docs/tutorials/confidential-compute-requests.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,11 @@ The [Typescript template](https://github.com/flashbots/suave-viem/tree/main/exam

In this case, we need to:

1. Craft a transaction on your chosen domain and sign it.
1. Craft a transaction on Goerli and sign it.
2. Append relevant details like the `decryptionCondition`, `kettleAddress`, `contract` and `chainId`.
3. Use a helper function like `toConfidentialRequest` to (i) place our signed transaction in `confidentialInputs` and (ii) replace the `data` field with a call to the appropriate method in the specified SUAVE contract.
3. Use a helper function like `toConfidentialRequest` to
1. place our signed transaction in `confidentialInputs` and
2. replace the `data` field with a call to the appropriate method in the specified SUAVE contract.

The [code which achieves this can be found here](https://github.com/flashbots/suave-viem/blob/main/examples/suave-web-demo/src/suave.ts) and looks like this:

Expand Down Expand Up @@ -187,7 +189,7 @@ The [**SUAPP Examples repo**](https://github.com/flashbots/suapp-examples) uses

:::

In particular, we can look at the [private order-flow auction example](https://github.com/flashbots/suapp-examples/blob/main/examples/app-ofa-private/main.go) to understand how to use the Golang SDK to craft more complex kinds of CCRs.
Let's look at the [private order-flow auction example](https://github.com/flashbots/suapp-examples/blob/main/examples/app-ofa-private/main.go) to understand how to use the Golang SDK to craft more complex kinds of CCRs.

The flow of this example is similar to the Typescript MEVShare demo directly above. However, we'll use it to demonstrate a full e2e flow with CCRs:

Expand Down
56 changes: 22 additions & 34 deletions docs/tutorials/deploy-contracts.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ Transaction hash: 0x9ae80af40bdafbc706108446dbbf7761a59f5bf544b46c97b9b0851dddaa

### Locally

You can follow the exact same method as above to deploy contracts to your local SUAVE devnet. You just need to have SUAVE running and use the pre-funded account we have setup for you:
You can follow the exact same method as above to deploy contracts to your local SUAVE devnet. You need to [have SUAVE running](/tutorials/run-suave) and use the pre-funded account we have setup for you:

```bash
forge create --rpc-url http://localhost:8545 --legacy \
Expand All @@ -81,25 +81,6 @@ Deployed to: 0xcbdF0322Cd79212e10b0dB72D775aE05B99c1796
Transaction hash: 0x9ae80af40bdafbc706108446dbbf7761a59f5bf544b46c97b9b0851dddaa3927
```

## Deploy with Remix

:::warning

This method is quick, but limited. You can deploy contracts using Remix and an injected web3 provider. However, you cannot send Confidential Compute Requests to those contracts from providers like MetaMask, so it is difficult to interact with your contracts once deployed.

:::

Follow these steps to deploy a contract via Remix:

1. Add the Rigil RPC to your MetaMask or equivalent wallet and connect to it:

<RPCButton />

2. Ensure you have rETH from the [Rigil ETH Faucet](https://faucet.rigil.suave.flashbots.net)
3. Go to the [Remix IDE](http://remix.ethereum.org/) and navigate to the bottom icon on the right-hand menu: "Deploy and Run Transactions".
4. Open the dropdown "Environment" menu and select "Injected Provider - MetaMask". It should show `Custom (16813125) network` directly below that field if this works correctly.
5. Write (or import) your contracts in the File Explorer tab, compile them, and deploy them as you usually would.

## SUAPP Examples

First, clone and set up the [SUAPP examples repo](https://github.com/flashbots/suapp-examples/):
Expand All @@ -120,23 +101,11 @@ You can compile the contracts in the repo with:
forge build
```

<details>
<summary>What is Forge?</summary>
<div>
<div>
<div>
`forge` is a part of the smart contract development toolchain we use in our examples, which you can learn more about in our [next tutorial](/tutorials/deploy-contracts). If you do not have it installed, you can do so quickly with:
<pre>curl -L https://foundry.paradigm.xyz | bash</pre>
</div>
</div>
</div>
</details>

### Locally

Now we can deploy and transact with any of the example contracts.

The `framework/framework.go` file defaults to your [local SUAVE devnet](/tutorials/run-suave). If you have that running, just `cd` into the relevant directory and run the `main.go` file. For instance, to deploy and transact with the example contract which demonstrates how updating state works for normal vs confidential requests, you can run:
Once you have [SUAVE running locally](/tutorials/run-suave), `cd` into the relevant directory and run the `main.go` file. For instance, to deploy and transact with the example contract which demonstrates how updating state works for normal vs confidential requests, you can run:

```bash
cd examples/onchain-state && go run main.go
Expand All @@ -149,7 +118,7 @@ You should see this message printed in your terminal if successful:
2. Send a confidential request that modifies the state
```

The `framework.go` and all of the `main.go` files use the Golang SDK, which you can read more about in our [developer guides](/resources/golang-sdk).
The `framework.go` and all of the `main.go` files use the Golang SDK, which you can read more about in our [resources section](/resources/golang-sdk).

### To Rigil

Expand Down Expand Up @@ -178,3 +147,22 @@ You should again see output like this logged in your terminal:
1. Send a confidential request that cannot modify the state
2. Send a confidential request that modifies the state
```

## Deploy with Remix

:::warning

This method is quick, but limited. You can deploy contracts using Remix and an injected web3 provider. However, you cannot send Confidential Compute Requests to those contracts from providers like MetaMask, so it is difficult to interact with your contracts once deployed.

:::

Follow these steps to deploy a contract via Remix:

1. Add the Rigil RPC to your MetaMask or equivalent wallet and connect to it:

<RPCButton />

2. Ensure you have rETH from the [Rigil ETH Faucet](https://faucet.rigil.suave.flashbots.net)
3. Go to the [Remix IDE](http://remix.ethereum.org/) and navigate to the bottom icon on the right-hand menu: "Deploy and Run Transactions".
4. Open the dropdown "Environment" menu and select "Injected Provider - MetaMask". It should show `Custom (16813125) network` directly below that field if this works correctly.
5. Write (or import) your contracts in the File Explorer tab, compile them, and deploy them as you usually would.
Loading

0 comments on commit f884e2e

Please sign in to comment.