Skip to content

Commit

Permalink
Forge replaced my README lmao
Browse files Browse the repository at this point in the history
  • Loading branch information
z80dev authored Oct 24, 2024
1 parent 6338fa9 commit 20ef679
Showing 1 changed file with 72 additions and 43 deletions.
115 changes: 72 additions & 43 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,66 +1,95 @@
## Foundry
# Huff, in Racket

**Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.**
Puff is an experimental Huff compiler implemented in Racket. It currently supports a small subset of full Huff functionality.

Foundry consists of:
# Current Status

- **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.
Very early WIP!

## Documentation
## Implemented

https://book.getfoundry.sh/
Not much yet, but we can compile a basic contract that has a single MAIN macro, imports other files, and references constants.

## Usage
- All opcodes
- `#define function` and `__FUNC_SIG`
- `#define error` and `__ERROR`
- `#define constant` and `[CONSTANT]` syntax for const references

### Build
## Not Implemented
- Calling macros/functions from Main
- Custom constructors
- Built-ins like __FUNC_SIG, etc.
- Lots of other stuff!

```shell
$ forge build
```
# Usage

### Test
## Requirements

```shell
$ forge test
```
- Racket
- Rust

### Format
### Racket Libs

```shell
$ forge fmt
```
- `threading-lib`
- `brag`

### Gas Snapshots
Install with:

```shell
$ forge snapshot
```
`make install_racket_libs`

### Anvil
## Build keccak library

```shell
$ anvil
```
Puff depends on the keccak implementation from [Alloy](https://github.com/alloy-rs/core).

### Deploy
We need a tiny bit of Rust code to build a library we can call from Racket over FFI. This is all handled by the makefile.

```shell
$ forge script script/Counter.s.sol:CounterScript --rpc-url <your_rpc_url> --private-key <your_private_key>
```
Clone the repository, then from its root, run:

### Cast
`make deps`

```shell
$ cast <subcommand>
```
## Run

Compile one of the example contracts:

`racket main.rkt -b examples/add_two.huff`

## [Optional] Compile executable

You can do this already with `raco exe main.rkt -o puffc` and then `raco distribute out puffc`. This gives you a directory (called `out`) containing an executable and the required lib.

I then ran `ln -s /home/z80/dev/puff/out/bin/puffc /home/z80/.local/bin/puffc` to create a symlink in a directory that's in my path, so I can call puffc from anywhere.

### Help
I'll be automating this in some way but if you're interested, that's how you do it

```shell
$ forge --help
$ anvil --help
$ cast --help
# Technical Documentation

## Compiler Phases

The `compile-src` function illustrates the compilation pipeline

``` racket
(define (compile-src src)
(~> src
lex ;; src -> tokens
parse ;; tokens -> syntax obj
syntax->datum ;; syntax obj -> AST
analyze-node ;; AST -> compiler data
compile-program-data ;; compiler data -> bytes
bytes->hex)) ;; bytes -> hex string
```

### Lexing

This happens in `puff/lexer.rkt`. In it we define some patterns we want to capture in the source code as specific tokens. This lets us have a much simpler and more explicit grammar.

### Parsing

We use the `brag` language to define our grammar in `huffparser.rkt`. With this grammar definintion, we get a `parse` function anywhere just by importing `huffparser.rkt`.

### Analysis

We define various phases of analysis in `analysis.rkt`. In this file we do all the work required to go from an AST to a `compiler-data` struct, which is a struct meant to contain all the data required to actually compile a contract. The `compiler-data` object essentiallyu acts as an enhanced AST, all the same data is contained but with the ability to easily and quickly perform lookups on labels, constants, errors, events, etc.

### Compilation

This happens in `puff.rkt`, `codegen.rkt`, and all the phases under `puff/phases`. We coordinate the various steps in `puff.rkt` but most of the actual compilation logic is implemented in various handlers in `codegen.rkt ` and the `phases`.

0 comments on commit 20ef679

Please sign in to comment.