Skip to content

Commit

Permalink
init repo
Browse files Browse the repository at this point in the history
  • Loading branch information
gakonst committed Dec 1, 2022
0 parents commit f8f41fd
Show file tree
Hide file tree
Showing 12 changed files with 294 additions and 0 deletions.
48 changes: 48 additions & 0 deletions .github/workflows/contracts.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: Solidity
on:
push:
branches:
- master
pull_request:

jobs:
tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2

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

- name: Pull library deps
working-directory: contracts
run: forge update

- name: Run forge tests
working-directory: contracts
run: forge test

bindings:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2

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

- name: Pull library deps
working-directory: contracts
run: forge update

- name: Build contracts before checking bindings are correct
working-directory: contracts
run: forge build

- name: Check bindings are correct
run: forge bind --bindings-path ./bindings --root ./contracts --crate-name bindings

# TODO: Add lints once forge fmt is in
55 changes: 55 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
on:
push:
branches:
- master
pull_request:

name: Rust

jobs:
tests-stable:
name: Tests (Stable)
runs-on: ubuntu-latest
env:
ETH_RPC_URL: https://eth-mainnet.alchemyapi.io/v2/Lc7oIGYeL_QvInzI0Wiu_pOZZDEKBrdf
steps:
- name: Checkout sources
uses: actions/checkout@v2

- name: Install toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: stable
profile: minimal
override: true

- uses: Swatinem/rust-cache@v1
with:
cache-on-failure: true

- name: cargo test
run: cargo test --all --all-features

lint:
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v2

- name: Install toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: nightly
profile: minimal
components: rustfmt, clippy
override: true

- uses: Swatinem/rust-cache@v1
with:
cache-on-failure: true

- name: cargo fmt
run: cargo +nightly fmt --all -- --check

- name: cargo clippy
run: cargo +nightly clippy --all --all-features -- -D warnings
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/target
out/
cache/
Cargo.lock
Empty file added .gitmodules
Empty file.
5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[workspace]
members = [
"bindings",
"app",
]
92 changes: 92 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# Foundry Rust Monorepo Template

![Rust](https://github.com/gakonst/foundry-rust-template/workflows/Rust/badge.svg)
![Solidity](https://github.com/gakonst/foundry-rust-template/workflows/Solidity/badge.svg)
[![Telegram Chat][tg-badge]][tg-url]

[tg-badge]:
https://img.shields.io/endpoint?color=neon&style=flat-square&url=https%3A%2F%2Ftg.sumanjay.workers.dev%2Ffoundry_rs
[tg-url]: https://t.me/foundry_rs

**Template for quickly getting started with developing Rust applications that
leverage Foundry for EVM smart contract development.**

Continuous Integration is already set up to test both your Rust and Solidity
code, as well as ensure formatting and that your Rust bindings match the
Solidity build artifacts.

## Directory Structure

The project is structured as a mixed Rust workspace with a Foundry project under
`contracts/` and typesafe auto-generated bindings to the contracts under
`bindings/`.

```
├── Cargo.toml
├── app // <-- Your Rust application logic
├── contracts // <- The smart contracts + tests using Foundry
├── bindings // <-- Generated bindings to the smart contracts' abis (like Typechain)
```

## Testing

Given the repository contains both Solidity and Rust code, there's 2 different
workflows.

### Solidity

Forge is using submodules to manage dependencies. Initialize the dependencies:

```bash
forge install
```

If you are in the root directory of the project, run:

```bash
forge test --root ./contracts
```

If you are in in `contracts/`:

```bash
forge test
```

### Rust

```
cargo test
```

## Generating Rust bindings to the contracts

Rust bindings to the contracts can be generated via `forge bind`, which requires
first building your contracts:

```
forge build --root ./contracts
forge bind --bindings-path ./bindings --root ./contracts --crate-name bindings
```

Any follow-on calls to `forge bind` will check that the generated bindings match
the ones under the build files. If you want to re-generate your bindings, pass
the `--overwrite` flag to your `forge bind` command.

## Installing Foundry

First run the command below to get `foundryup`, the Foundry toolchain installer:

```sh
curl -L https://foundry.paradigm.xyz | bash
```

Then, in a new terminal session or after reloading your `PATH`, run it to get
the latest `forge` and `cast` binaries:

```sh
foundryup
```

For more, see the official
[docs](https://github.com/gakonst/foundry#installation).
12 changes: 12 additions & 0 deletions app/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "app"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
bindings = { path = "../bindings" }
ethers = { git = "https://github.com/gakonst/ethers-rs", default-features = false }
eyre = "0.6.6"
tokio = { version = "1.17.0", features = ["macros"] }
22 changes: 22 additions & 0 deletions app/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use bindings::my_contract::MyContract;

use ethers::{prelude::Middleware, providers::Provider, types::Address};

use eyre::Result;
use std::convert::TryFrom;
use std::sync::Arc;

#[tokio::main]
async fn main() -> Result<()> {
let provider = Provider::try_from(
"https://eth-rinkeby.alchemyapi.io/v2/Lc7oIGYeL_QvInzI0Wiu_pOZZDEKBrdf",
)?;
let provider = Arc::new(provider);

let address = "0x0000000000000000000000000000000000000000".parse::<Address>()?;

let contract = MyContract::new(address, provider);
let blk = contract.client().get_block_number().await?;
println!("Hello, world! {}", blk);
Ok(())
}
6 changes: 6 additions & 0 deletions contracts/foundry.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[profile.default]
src = 'src'
out = 'out'
libs = ['lib']

# See more config options https://github.com/foundry-rs/foundry/tree/master/config
12 changes: 12 additions & 0 deletions 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 "forge-std/Script.sol";

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

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

contract Counter {
uint256 public number;

function setNumber(uint256 newNumber) public {
number = newNumber;
}

function increment() public {
number++;
}
}
24 changes: 24 additions & 0 deletions contracts/test/Counter.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import "forge-std/Test.sol";
import "../src/Counter.sol";

contract CounterTest is Test {
Counter public counter;

function setUp() public {
counter = new Counter();
counter.setNumber(0);
}

function testIncrement() public {
counter.increment();
assertEq(counter.number(), 1);
}

function testSetNumber(uint256 x) public {
counter.setNumber(x);
assertEq(counter.number(), x);
}
}

0 comments on commit f8f41fd

Please sign in to comment.