Skip to content

Commit

Permalink
suave (#4)
Browse files Browse the repository at this point in the history
* remove CHANGELOG.md symlink

* add transactionRequest test, update SuaveTransactionRequest definition

* add tx formatter

* disable anvil calls in vitest setup (run with SKIP_GLOBAL_SETUP=true)

* add test:e2e in playgrounds/bun/

* update chain id, add local devnet config

* working SuaveTransactionRequest impl

* infer isConfidential from confidentialInputs

* infer tx type in SuaveTransactionRequest

* add getTransaction[Receipt] to playground test

* revise SuaveTransaction formatter/type

* harden SuaveTransaction[Request] formatter/type

* add SuaveTransaction serialization constructs

* refactor type defs; make rpc types generic, deserialized types restrictive

* experimental serializer

* fix rlp signature bugs; working CCR transactionRequests

* push lint fixes

* cleanup, remove debug console logs

* compartmentalize wallet action overrides with new fn: getSuaveWallet

* support all tx types

* remove bad 'from' addrs

* lint

* fix bad imports

* make privatekey optional in getSuaveWallet

* lint

* fix some type-related bugs + formatter tests

* remove junk comments

* add block formatter tests

* remove unused fields in block formatter

* add tx receipt formatter test

* clean up duplicate logic in sendTransaction override, add examples in playground

* wait for fund tx to land in playground example

* lint

* re-enable anvil backend for tests

* cleanup junk comments, remove unused arg

* stricter input requirement for serializeConfidentialComputeRequest

* add links to spec in doc-comments

* use idiomatic errors in tx serializers

* add parsers in parsers.ts, tests

* add parseTransactionSuave; covers all supported tx types; +test

* chore: forge init

* forge install: forge-std

v1.7.1

* fix pre-signature ccRecord serialization scheme

* replace 'executionNode' with 'kettleAddress', remove invalid instances from SuaveTx

* add deployment example in playground

* clean up & fix bugs in serializer/signer

- working ccRequest & contract deployment
- made example useless so it will compile
  - will fix this next

* cleanup

* add deploy script for mev-share contract, clean up

- deploy mev-share suave contract w/ forge
- convert index-style imports to tiny mod imports
- fix build errors from new type changes

* tighten up types

* clean up deploy script

* add working mev-share bid example in playgrounds/bun

* comment out old examples; saving for later isolated examples

* make chainId optional in TransactionRequestSuave

* move getSuaveWallet to suaveRigil.newWallet

* move playground code to examples/suave/

* lint

* delete old code comments

* insert suave chainId if missing

* add 'suaveRigil.newPublicClient'

* chore: format

---------

Co-authored-by: zeroXbrock <[email protected]>
  • Loading branch information
zeroXbrock and zeroXbrock authored Nov 22, 2023
1 parent b5ac97c commit fa23389
Show file tree
Hide file tree
Showing 32 changed files with 1,848 additions and 526 deletions.
6 changes: 3 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[submodule "contracts/lib/forge-std"]
path = contracts/lib/forge-std
url = https://github.com/foundry-rs/forge-std
[submodule "examples/suave/contracts/lib/suave-geth"]
path = examples/suave/contracts/lib/suave-geth
url = https://github.com/flashbots/suave-geth
1 change: 0 additions & 1 deletion CHANGELOG.md

This file was deleted.

3 changes: 2 additions & 1 deletion biome.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
"tsconfig.json",
"tsconfig.*.json",
"generated.ts",
"vectors/*.json"
"vectors/*.json",
"examples"
]
},
"formatter": {
Expand Down
Binary file modified bun.lockb
Binary file not shown.
4 changes: 4 additions & 0 deletions examples/suave/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
PRIVATE_KEY=0x91ab9a7e53c220e6210460b65a7a3bb2ca181412a8a7b43ff336b3df1737ce12
KETTLE_ADDRESS=0xb5feafbdd752ad52afb7e1bd2e40432a485bbb7f
SUAVE_RPC_URL_HTTP=http://localhost:8545
GOERLI_RPC_URL_HTTP=
42 changes: 42 additions & 0 deletions examples/suave/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# suave example

## build contracts

Forge will install the required solidity dependencies into `examples/suave/contracts/lib/`.

```sh
# from examples/suave/contracts/

forge install
forge build
```

## deploy contracts

We use a forge script to deploy our contracts. Normally we'd use `forge create` for this but because we rely on (deeply-nested) suave-geth contracts, this is a bit cleaner.

```sh
# from examples/suave/contracts/

# do a dry run to see that your dependencies are set up correctly:
forge script DeployContracts

# populate environment vars using this project's .env file
source ../.env

# send real deployment transactions with the --broadcast flag
forge script --broadcast --rpc-url $RPC_URL_HTTP --private-key $PRIVATE_KEY DeployContracts
```

Then populate your .env file with the new bid contract address.

```sh
# from examples/suave/contracts/
echo "BID_CONTRACT_ADDRESS=$(cat broadcast/Deploy.s.sol/16813125/run-latest.json | jq -r '.receipts[0].contractAddress')" >> ../.env
```

## run example

```bash
bun run index.ts
```
76 changes: 76 additions & 0 deletions examples/suave/bids/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import {
Address,
Hex,
encodeAbiParameters,
encodeFunctionData,
toHex,
} from 'viem'
import precompiles from 'viem/chains/suave/precompiles'
import { SuaveTxTypes, TransactionRequestSuave } from 'viem/chains/suave/types'
import MevShareBidContract from '../contracts/out/bids.sol/MevShareBidContract.json'

export interface MevShareBid {
allowedPeekers: Address[]
allowedStores: Address[]
blockNumber: bigint
signedTx: Hex
mevShareContract: Address
kettle: Address
chainId: number
}

/** Helper class to create MEV-Share bids on SUAVE. */
export class MevShareBid {
constructor(
blockNumber: bigint,
signedTx: Hex,
kettle: Address,
mevShareContract: Address,
chainId: number,
) {
this.blockNumber = blockNumber
this.signedTx = signedTx
this.kettle = kettle
this.mevShareContract = mevShareContract
this.chainId = chainId
this.allowedPeekers = [
// no idea what I'm doing here
precompiles.ANYALLOWED,
]
this.allowedStores = []
}

/** Encodes calldata to call the `newBid` function. */
private newBidCalldata() {
return encodeFunctionData({
abi: MevShareBidContract.abi,
functionName: 'newBid',
args: [this.blockNumber, this.allowedPeekers, this.allowedStores],
})
}

/** Wraps `signedTx` in a bundle, then ABI-encodes it as bytes for `confidentialInputs`. */
private confidentialInputsBytes(): Hex {
const bundleBytes = toHex(
JSON.stringify({
txs: [this.signedTx],
revertingHashes: [],
}),
)
return encodeAbiParameters([{ type: 'bytes' }], [bundleBytes])
}

/** Encodes this bid as a ConfidentialComputeRequest, which can be sent to SUAVE. */
toConfidentialRequest(): TransactionRequestSuave {
return {
to: this.mevShareContract,
data: this.newBidCalldata(),
type: SuaveTxTypes.ConfidentialRequest,
gas: 500000n,
gasPrice: 1000000000n,
chainId: this.chainId,
kettleAddress: this.kettle,
confidentialInputs: this.confidentialInputsBytes(),
}
}
}
34 changes: 34 additions & 0 deletions examples/suave/contracts/.github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: test

on: workflow_dispatch

env:
FOUNDRY_PROFILE: ci

jobs:
check:
strategy:
fail-fast: true

name: Foundry project
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
submodules: recursive

- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
with:
version: nightly

- name: Run Forge build
run: |
forge --version
forge build --sizes
id: build

- name: Run Forge tests
run: |
forge test -vvv
id: test
15 changes: 15 additions & 0 deletions examples/suave/contracts/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Compiler files
cache/
out/

# Ignores development broadcast logs
!/broadcast
/broadcast/*/31337/
/broadcast/**/dry-run/
**/broadcast

# Docs
docs/

# Dotenv file
.env
66 changes: 66 additions & 0 deletions examples/suave/contracts/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
## Foundry

**Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.**

Foundry consists of:

- **Forge**: Ethereum testing framework (like Truffle, Hardhat and DappTools).
- **Cast**: Swiss army knife for interacting with EVM smart contracts, sending transactions and getting chain data.
- **Anvil**: Local Ethereum node, akin to Ganache, Hardhat Network.
- **Chisel**: Fast, utilitarian, and verbose solidity REPL.

## Documentation

https://book.getfoundry.sh/

## Usage

### Build

```shell
$ forge build
```

### Test

```shell
$ forge test
```

### Format

```shell
$ forge fmt
```

### Gas Snapshots

```shell
$ forge snapshot
```

### Anvil

```shell
$ anvil
```

### Deploy

```shell
$ forge script script/Counter.s.sol:CounterScript --rpc-url <your_rpc_url> --private-key <your_private_key>
```

### Cast

```shell
$ cast <subcommand>
```

### Help

```shell
$ forge --help
$ anvil --help
$ cast --help
```
9 changes: 9 additions & 0 deletions examples/suave/contracts/foundry.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[profile.default]
src = "src"
out = "out"
libs = ["lib"]

# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options
remappings = [
"suave/=lib/suave-geth/suave/sol/"
]
1 change: 1 addition & 0 deletions examples/suave/contracts/lib/suave-geth
Submodule suave-geth added at 57cbeb
12 changes: 12 additions & 0 deletions examples/suave/contracts/script/Counter.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import {Script, console2} from "forge-std/Script.sol";

contract CounterScript is Script {
function setUp() public {}

function run() public {
vm.broadcast();
}
}
15 changes: 15 additions & 0 deletions examples/suave/contracts/script/Deploy.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import {Script, console2} from "forge-std/Script.sol";
import {MevShareBidContract} from "suave/standard_peekers/bids.sol";

contract DeployContracts is Script {
function setUp() public {}

function run() public {
vm.broadcast();
MevShareBidContract bidContract = new MevShareBidContract();
console2.log("bid contract deployed", address(bidContract));
}
}
53 changes: 53 additions & 0 deletions examples/suave/contracts/src/ConfidentialWithLogs.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import "suave/libraries/Suave.sol";

contract ConfidentialWithLogs {
event SimResultEvent(
uint64 egp
);

event Test(
uint64 num
);

constructor() {
emit Test(1);
}

fallback() external {
emit Test(2);
}

function fetchBidConfidentialBundleData() public returns (bytes memory x) {
emit Test(101);
// require(Suave.isConfidential(), "not confidential");

// bytes memory confidentialInputs = Suave.confidentialInputs();
// return abi.decode(confidentialInputs, (bytes));
x = hex"deadbeef";
}

// note: this enables the result of the confidential compute request (CCR)
// to be emitted on chain
function emitSimResultEvent(uint64 egp) public {
emit SimResultEvent(egp);
}

// note: because of confidential execution,
// you will not see your input as input to the function
function helloWorld() external returns (bytes memory) {
// 0. ensure confidential execution
// require(Suave.isConfidential(), "not confidential");

// 1. fetch bundle data
bytes memory bundleData = this.fetchBidConfidentialBundleData();

// 2. sim bundle and get effective gas price
uint64 effectiveGasPrice = Suave.simulateBundle(bundleData);

// note: this enables the computation result to be emitted on chain
return bytes.concat(this.emitSimResultEvent.selector, abi.encode(effectiveGasPrice));
}
}
Loading

0 comments on commit fa23389

Please sign in to comment.