• Stars
    star
    517
  • Rank 83,583 (Top 2 %)
  • Language
  • Created about 2 years ago
  • Updated 9 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Foundry Cheatsheet

Foundry Cheatsheet

Foundry GitHub - https://github.com/foundry-rs
Foundry Book - https://book.getfoundry.sh/
Installing Foundry - https://github.com/foundry-rs/foundry#installation

Foundry is made up of three components:

Forge: Ethereum testing framework (like Truffle, Hardhat and DappTools).
Cast: CLI for interacting with EVM smart contracts, sending transactions and getting chain data.
Anvil: local Ethereum node, similar to Ganache or Hardhat Network.

Forge includes both a CLI as well as a standard library.

For an introduction to Foundry, check out these resources:

For support, check out the Telegram channel here

Initializing a new project

Initialize a new project from an empty folder:

forge init

Or define a new folder in which to create your project:

forge init my-app

This creates a new project with 4 folders:

src - An example smart contract and where your smart contracts will live.

script - An example deployment script

test - An example test

lib - This is similar to node_modules

Remappings

Forge can remap dependencies to make them easier to import. Forge will automatically try to deduce some remappings for you:

$ forge remappings

ds-test/=lib/solmate/lib/ds-test/src/
forge-std/=lib/forge-std/src/

If you're using VS Code, you can configure your remappings by installing vscode-solidity.

Learn more about how remappings work here

Testing

You can execute tests by running the forge test script.

forge test

Any contract with a function that starts with test is considered to be a test.

function testAssertEquality() public {
  int some_int = 1;
  assertEq(1, some_int);
}

Usually, tests will be placed in src/test by convention and end with .t.sol.

Foundry uses Dappsys Test (DSTest) to provide basic logging and assertion functionality. It's included in the Forge Standard Library.

It includes assertions such as:

assertTrue
assertEq
assertEqDecimal
assertEq32
assertEq0
assertGt
assertGtDecimal
assertGe
assertGeDecimal
assertLt
assertLtDecimal
assertLe
assertLeDecimal

You can view all of the assertion functions available here.

Let's say you start with a basic Counter contract that looks like this (src/Counter.sol):

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

contract Counter {
    int private count;
    
    constructor(int _count) {
        count = _count;
    }

    function incrementCounter() public {
        count += 1;
    }
    function decrementCounter() public {
        count -= 1;
    }

    function getCount() public view returns (int) {
        return count;
    }
}

Our test might look like this (test/Counter.t.sol):

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

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

contract ContractTest is Test {
    Counter counter;
    function setUp() public {
        counter = new Counter(10);
    }

    function testGetCount() public {
        int value = counter.getCount();
        assertEq(value, 10);
        emit log_int(value);
    }

    function testIncrement() public {
        counter.incrementCounter();
        counter.incrementCounter();
        int value = counter.getCount();
        assertEq(value, 12);
        emit log_int(value);
    }

    function testDecrement() public {
        counter.decrementCounter();
        int value = counter.getCount();
        assertEq(value, 9);
        emit log_int(value);
    }
}

Here, we are using assertEq to assert equality. You can view all of the assertion functions available here.

Logs and traces

You'll also notice that we're logging values using log_int. You log can most types of values this way:

emit log(string);

emit log_address(address);
emit log_bytes32(bytes32);
emit log_int(int);
emit log_uint(uint);
emit log_bytes(bytes);
emit log_string(string);

emit log_named_address(string key, address val);
emit log_named_bytes32(string key, bytes32 val);
emit log_named_decimal_int(string key, int val, uint decimals);
emit log_named_decimal_uint(string key, uint val, uint decimals);
emit log_named_int(string key, int val);
emit log_named_uint(string key, uint val);
emit log_named_bytes(string key, bytes val);
emit log_named_string(string key, string val);

The default behavior for forge test is to only display a summary of passing and failing tests. You can control this behavior by increasing the verbosity (using the -v flag). Each level of verbosity adds more information:

Level 2 (-vv): Logs emitted during tests are also displayed. That includes assertion errors from tests, showing information such as expected vs actual.
Level 3 (-vvv): Stack traces for failing tests are also displayed.
Level 4 (-vvvv): Stack traces for all tests are displayed, and setup traces for failing tests are displayed.
Level 5 (-vvvvv): Stack traces and setup traces are always displayed.

For our logs to show up, we need to run test with at least the -vv flag:

forge test -vv

Cheatcodes

Cheatcodes give you additional assertions, the ability to alter the state of the EVM, mock data, and more.

For example, you can mock a user with prank and startPrank:

address bob = address(0x1);
vm.startPrank(bob);

Set the nonce of the given account with setNonce.

vm.setNonce(address(100), 1234);

Set the block number with roll:

vm.roll(100);
emit log_uint(block.number); // 100

Or set the block timestamp with warp:

vm.warp(1641070800);
emit log_uint(block.timestamp); // 1641070800

See a reference of all of the cheatcodes here

Mocking a user

As mentioned, you can mock / emulate a user using either .prank or .startPrank. Let's take a look at how this might work.

Let's say we have an ERC721 contract and we'd like to make sure that only the owner of a token could transfer or burn that token. Our tests might look something like this:

// only the owner can transfer
function testTransferToken() public {
    // mint the token to bob's address
    erc721 = new ERC721();
    erc721.mint(bob, 0);

    // emulate bob
    vm.startPrank(bob);

    // transfer to mary
    erc721.safeTransferFrom(bob, mary, 0);

    // check to make sure mary is the new owner
    address owner_of = erc721.ownerOf(0);
    assertEq(mary, owner_of);
}

// only the owner can burn
function testBurn() public {
    erc721 = new ERC721();
    erc721.mint(bob, 0);
    vm.startPrank(bob);
    erc721.burn(0);
}

Fuzzing

Fuzzing allows us to define function parameter types and the testing framework will populate these values at runtime.

If it does find an input that causes the test to fail, it will return it so you can create a regression test.

For instance, we can create a test function to receive a function argument, and use the value in our test without ever having to define what it is.

For this contract:

// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

contract HelloWorld {
  string private greeting;
  uint public version = 0;
  
  constructor (string memory _greeting) {
    greeting = _greeting;
  }

  function greet() public view returns(string memory) {
    return greeting;
  }
}

We could create this test:

contract ContractTest is Test {
  function testFuzzing(string memory _greeting) public {
      HelloWorld hello = new HelloWorld(_greeting);
      assertEq(
          hello.greet(),
          _greeting
      );
  }
}

Gas

You can easily print a pretty looking gas report of your tested functions:

forge test --gas-report

ABIs

ABIs will be located in the out directory after running either a build with forge build or a deployment with a script.

Test Options

You can get a full list of testing options by running the --help command:

forge test --help

Scripts & deploying

Foundry recently released Solidity Scripting.

Scripting gives you a lot of control over how you can deploy contracts using Solidity scripts, and I believe is meant to replace forge create which was previously how you could deploy contracts.

From Foundry Book:

Solidity scripts are like the scripts you write when working with tools like Hardhat; what makes Solidity scripting different is that they are written in Solidity instead of JavaScript, and they are run on the fast Foundry EVM backend, which provides dry-run capabilities.

Let's look at how to deploy our contract using Solidity Scripting.

Scripts are executed by calling the function named run, our entrypoint:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import "forge-std/Script.sol";

import {Counter} from "src/Counter.sol";

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

    function run() public {
        vm.startBroadcast();
        new Counter(10);
        vm.stopBroadcast();
    }
}

Now we can use this script to deploy our smart contract to either a live or test network. 🚀

Using the address that calls the test contract or the address provided as the sender, startBroadcast and startBroadcast(address) will have all subsequent calls (at this call depth only) create transactions that can later be signed and sent onchain.

stopBroadcast stops collecting transactions for later on-chain broadcasting.

You can also use broadcast, using the address that calls the test contract, has the next call (at this call depth only) create a transaction that can later be signed and sent onchain

Or broadcast(address) using the address provided as the sender, have only the next call (at this call depth) create a transaction that can later be signed and sent onchain.

Deploying locally

Next start Anvil, the local testnet:

anvil

Once started, Anvil will give you a local RPC endpoint as well as a handful of Private Keys and Accounts that you can use.

We can now use the local RPC along with one of the private keys to deploy locally:

forge script script/Contract.s.sol:ContractScript --fork-url http://localhost:8545 \
--private-key $PRIVATE_KEY --broadcast

Using cast to perform Ethereum RPC calls

Once the contract has been deployed locally, Anvil will log out the contract address.

Next, set the contract address as an environment variable:

export CONTRACT_ADDRESS=<contract-address>

We can then test sending transactions to it with cast send.

cast send $CONTRACT_ADDRESS "incrementCounter()" \
--private-key $PRIVATE_KEY

We can then perform read operations with cast call:

cast call $CONTRACT_ADDRESS "getCount()(int)"

Deploying to a network

Now that we've deployed and tested locally, we can deploy to a network.

To do so, run the following script:

forge script script/Contract.s.sol:ContractScript --rpc-url $RPC_URL \
 --private-key $PRIVATE_KEY --broadcast

Once the contract has been deployed to the network, we can use cast send to test sending transactions to it:

cast send $CONTRACT_ADDRESS "incrementCounter()" --rpc-url $RPC_URL \
--private-key $PRIVATE_KEY 

We can then perform read operations with cast call:

cast call $CONTRACT_ADDRESS "getCount()(int)" --rpc-url $RPC_URL

Cast Options

You can get a full list of commands by running the --help command:

cast --help

More Repositories

1

awesome-aws-amplify

Curated list of AWS Amplify Resources
1,777
star
2

polygon-ethereum-nextjs-marketplace

A full stack digital marketplace running on Ethereum with Polygon & Next.js
JavaScript
1,287
star
3

full-stack-ethereum

Building full stack apps with Solidity, Ethers.js, Hardhat, and The Graph
TypeScript
801
star
4

react-native-ai

Full stack framework for building cross-platform mobile AI apps
TypeScript
739
star
5

semantic-search-nextjs-pinecone-langchain-chatgpt

Embeds text files into vectors, stores them on Pinecone, and enables semantic search using GPT3 and Langchain in a Next.js UI
TypeScript
726
star
6

awesome-aws-appsync

Curated list of AWS AppSync Resources
625
star
7

gpt-travel-advisor

reference architecture for building a travel application with GPT3
TypeScript
538
star
8

complete-guide-to-full-stack-solana-development

Code examples for the blog post titled The Complete Guide to Full Stack Solana Development with React, Anchor, Rust, and Phantom
JavaScript
474
star
9

dynamodb-documentclient-cheat-sheet

DynamoDB JavaScript DocumentClient cheat sheet
443
star
10

full-stack-web3

A full stack web3 on-chain blog and CMS
JavaScript
419
star
11

next.js-amplify-workshop

AWS Amplify Next.js workshop
JavaScript
360
star
12

gatsby-auth-starter-aws-amplify

Starter Project with Authentication with Gatsby & AWS Amplify
JavaScript
320
star
13

gpt-fine-tuning-with-nodejs

GPT Fine-Tuning using Node.js - an easy to use starter project
JavaScript
250
star
14

full-stack-serverless-code

Code examples for my book Full Stack Serverless with O'Reilly Publications
JavaScript
244
star
15

openai-functions-god-app

TypeScript
243
star
16

heard

React Native Enterprise Social Messaging App
JavaScript
236
star
17

aws-appsync-react-workshop

Building real-time offline-ready Applications with React, GraphQL & AWS AppSync
JavaScript
228
star
18

nextjs-chatgpt-plugin-starter

ChatGPT plugin starter project using Next.js
TypeScript
209
star
19

micro-frontend-example

Building Micro Frontends with React, Vue, and Single-spa
JavaScript
207
star
20

amplify-photo-sharing-workshop

Building full-stack cloud apps with AWS Amplify and React
JavaScript
197
star
21

chicken-tikka-masala-recipe

Nader's chicken tikka masala recipe
PHP
192
star
22

decentralized-identity-example

An authentication system built with Ceramic & self.id
JavaScript
190
star
23

aws-amplify-workshop-react

Building Serverless React Applications with AWS Amplify
172
star
24

building-a-subgraph-workshop

In this workshop you'll learn how to build an NFT Subgraph using any smart contract or smart contracts.
TypeScript
165
star
25

graphql-recipes

A list of GraphQL recipes that, when used with the Amplify CLI, will deploy an entire AWS AppSync GraphQL backend.
158
star
26

next.js-cdk-amplify-workshop

Full stack serverless workshop with Next.js, CDK, and AWS Amplify
JavaScript
157
star
27

titter

Decentralized Twitter prototype built with Polygon, GraphQL, Next.js, Ceramic, Arweave, and Bundlr
JavaScript
152
star
28

supabase-nextjs-auth

Example project implementing authentication, authorization, and routing with Next.js and Supabase
JavaScript
150
star
29

supabase-next.js

Full stack app built with Supabase and Next.js
JavaScript
149
star
30

react-native-in-action

React Native in Action, written for Manning Publications
146
star
31

write-with-me

Real-time Collaborative Markdown Editor
JavaScript
144
star
32

foundry-workshop

Building and testing smart contracts with Foundry
Solidity
144
star
33

prompt-engineering-for-javascript-developers

Notes summarized from ChatGPT Prompt Engineering for Developers by DeepLearning.ai
143
star
34

aws-amplify-workshop-react-native

Building Cloud-enabled Mobile Applications with React Native & AWS Amplify
JavaScript
139
star
35

lens-protocol-frontend

Example of a basic front end built on Lens Protocol
JavaScript
136
star
36

cdk-graphql-backend

A real-time GraphQL API deployed with CDK using AWS AppSync, AWS Lambda, and DynamoDB
TypeScript
131
star
37

create-new-cli

Create your own CLI using a series of simple commands.
JavaScript
128
star
38

perma

Perma is a web3 prototype of permanent video storage and viewing using Next.js, Arweave, and Bundlr.
JavaScript
120
star
39

appsync-graphql-real-time-canvas

Collaborative real-time canvas built with GraphQL, AWS AppSync, & React Canvas Draw
JavaScript
119
star
40

full-stack-ethereum-marketplace-workshop

Build a Full Stack Marketplace on Ethereum with React, Solidity, Hardhat, and Ethers.js
JavaScript
118
star
41

hype-beats

Real-time Collaborative Beatbox with React & GraphQL
JavaScript
111
star
42

amplify-auth-demo

Demo of OAuth + Username / Password authentication in AWS Amplify
JavaScript
111
star
43

next.js-authentication-aws

This project deploys a Next.js project to AWS with comprehensive authentication enabled
JavaScript
104
star
44

this-or-that

This or that - Real-time atomic voting app built with AWS Amplify
CSS
98
star
45

react-native-deep-linking

Deep Linking set up in a React Native App
Objective-C
96
star
46

beginning-webpack

This repository goes along with the medium post titled "Beginner's guide to Webpack"
JavaScript
95
star
47

react-native-bootcamp

React Native Bootcamp Materials for TylerMcginnis.com
94
star
48

react-native-mobx-list-app

React Native + Mobx List Application
JavaScript
91
star
49

appsync-auth-and-unauth

How to allow both authenticated & unauthenticated access to an API
JavaScript
91
star
50

aws-amplify-workshop-web

Building web applications with React & AWS Amplify
JavaScript
90
star
51

full-stack-ethereum-workshop

Building full stack dapps on the EVM with Hardhat, React, and Ethers.js
HTML
89
star
52

sign-in-with-ethereum-authentication-flow

Example implementation of how to implement Sign In with Ethereum
JavaScript
86
star
53

react-notes

React notes tutorial
JavaScript
84
star
54

vue-graphql-appsync

Vue example using GraphQL with AWS AppSync
JavaScript
81
star
55

custom-nft-subgraph-workshop

79
star
56

lens-pwa

Lens PWA
TypeScript
79
star
57

amplify-datastore-example

Example of basic app using Amplify DataStore
JavaScript
78
star
58

lens-shadcn

Example application combining Lens Protocol, WalletConnect, Next.js, and ShadCN
TypeScript
78
star
59

amplify-with-cdk

An example project showing how to mix CDK with AWS Amplify
TypeScript
77
star
60

react-aws-live-streaming

This project shows how to implement a live-streaming platform using AWS and React
JavaScript
73
star
61

react-native-navigation-v2

Up and running with React Native Navigation - V2 - by Wix
JavaScript
73
star
62

bored-ape-yacht-club-api-and-subgraph

Graph Protocol Subgraph / API for querying Bored Ape Yacht Club NFT data with full text search
TypeScript
70
star
63

react-appsync-graphql-recipe-app

Example application using React + AWS AppSync + GraphQL
JavaScript
70
star
64

react-amplify-appsync-files-s3

An example project showing how to upload and download public and private images in GraphQL using AppSync and S3
JavaScript
70
star
65

react-strict-dom-example

JavaScript
68
star
66

full-stack-react-native-appsync-workshop

Building Full Stack GraphQL Applications with React Native & AWS AppSync
JavaScript
67
star
67

speakerchat

SpeakerChat - Real-time Event Q&A Platform with Markdown Support
JavaScript
66
star
68

react-p2p-messaging

A real-time peer-to-peer messaging app built with React & Gun.js
JavaScript
65
star
69

graphql-suspense

Lightweight component that allows you to interact with a GraphQL API using React Suspense
JavaScript
65
star
70

nuxt-supabase-full-multi-user-blog

Build a mult-user blogging app with Supabase and Nuxt.js
Vue
65
star
71

archive-forever

HTML
63
star
72

next.js-tailwind-authentication

A Next.js authentication starter built with Tailwind and AWS Amplify
JavaScript
63
star
73

near-subgraph-workshop

Building a NEAR NFT API with The Graph
60
star
74

react-authentication-in-depth

Example of User Authentication using React with React Router and AWS Amplify
JavaScript
60
star
75

graphql-api-cdk-serverless-postgres

TypeScript
59
star
76

xmtp-chat-app-nextjs

Real-time encrypted chat, built with XMTP and Next.js
TypeScript
58
star
77

curious-cases-of-graphql

Code and examples from my talk - Curious Cases of GraphQL
57
star
78

gasless-transactions-example

Example of Gasless Transactions with Biconomy
JavaScript
57
star
79

react-chatbots

Building Chatbots with React, Amazon Lex, AWS Lambda, & AWS Amplify
JavaScript
56
star
80

react-native-lens-example

Example app built with React Native Lens UI Kit
JavaScript
55
star
81

lens-protocol-workshop

Introduction to web3 social media with Next.js and Lens Protocol
TypeScript
54
star
82

zora-nextjs-app

Example Full Stack App built with Next.js, Zora, Tailwind, and The Graph
TypeScript
54
star
83

arweave-workshop

JavaScript
50
star
84

lens-gated-publications

Example application implementing gated Lens posts, encryption, and decryption
JavaScript
49
star
85

graphql-search

Implementing Search in GraphQL using AWS AppSync & React Apollo
JavaScript
49
star
86

basic-amplify-storage-example

A basic example app showing how to add storage with Amazon S3
JavaScript
49
star
87

production-ready-vue-authentication

How to implement a real user authentication flow in Vue with Vue Router & AWS Amplify.
Vue
48
star
88

build-an-authenticated-api-with-cdk

Workshop - Build an authenticated CDK back end
TypeScript
48
star
89

real-time-image-tracking

Real-time image tracking with React, GraphQL, and AWS AppSync
JavaScript
48
star
90

draw-together

TypeScript
47
star
91

appsync-lambda-ai

Demo of using a GraphQL resolver to hit a lambda function, then hit a few AI services, and return the response.
JavaScript
47
star
92

appsync-react-native-with-user-authorization

End to end React Native + AWS AppSync GraphQL application with queries, mutations, subscriptions, & user authentication & authorization
JavaScript
47
star
93

openzeppelin-nft-api

Building NFT APIs with OpenZeppelin and The Graph
46
star
94

cryptocoven-api

Cryptocoven Graph API
TypeScript
46
star
95

transilator

Text translation and synthesization Chrome plugin
JavaScript
46
star
96

basic-serverless-api

A basic full stack example of building an API with AWS Amplify, Amazon API Gateway, AWS Lambda, and Amazon DynamoDB
JavaScript
46
star
97

terminal-portfolio

TypeScript
45
star
98

react-native-navigator-experimental-redux

React Native Navigator Experimental with Redux
JavaScript
45
star
99

next.js-amplify-datastore

An example app using Amplify DataStore with Next.js for static site generation, pre-rendering, and SSR
JavaScript
45
star
100

xp-mobile-account-abstraction

TypeScript
43
star