> For the complete documentation index, see [llms.txt](https://www.ankitavirani.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://www.ankitavirani.com/experience/web3-toolkits/foundry.md).

# Foundry

### 1. Introduction to Foundry 🏗️

Foundry is a blazing fast, portable, and modular toolkit for Ethereum application development. It's designed to make smart contract development, testing, and deployment more efficient and developer-friendly.

### 2. Installation and Setup 🔧

To install Foundry, follow these steps:

```bash
# Install Foundry
curl -L <https://foundry.paradigm.xyz> | bash

# Update PATH and load env variables
source ~/.bashrc

# Install Foundry components
foundryup
```

After installation, verify the setup:

```bash
forge --version
cast --version
anvil --version
```

### 3. Core Concepts 🧠

Foundry consists of three main components:

* **Forge:** A testing framework for Ethereum smart contracts
* **Cast:** A command-line tool for interacting with Ethereum RPC nodes
* **Anvil:** A local Ethereum node for development purposes
* **Chisel**: An interactive Solidity REPL (Read-Eval-Print Loop) for quick experimentation and debugging

### 4. Key Features 🌟

* Fast compilation and testing
* Solidity-native testing
* Flexible debugging
* Fuzz testing
* Gas optimization
* Forking capabilities

### 5. Foundry Architecture 🏛️

<figure><img src="/files/MtLO9Kb4XOMj5GbVlZZM" alt=""><figcaption></figcaption></figure>

### 6. User Flow 🔄

<figure><img src="/files/6Sp3qaRsxHx60eKtkBF3" alt=""><figcaption></figcaption></figure>

### 7. Solidity Basics to Advanced Concepts 📚

#### 7.1 Basic Structure of a Solidity Contract

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract MyContract {
    // State variables
    uint256 public myNumber;

    // Constructor
    constructor(uint256 _initialNumber) {
        myNumber = _initialNumber;
    }

    // Functions
    function setNumber(uint256 _newNumber) public {
        myNumber = _newNumber;
    }

    function getNumber() public view returns (uint256) {
        return myNumber;
    }
}
```

#### 7.2 Advanced Solidity Concepts

#### 7.2.1 Inheritance and Interfaces

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface ICounter {
    function increment() external;
    function getCount() external view returns (uint256);
}

contract Counter is ICounter {
    uint256 private count;

    function increment() external override {
        count++;
    }

    function getCount() external view override returns (uint256) {
        return count;
    }
}

contract AdvancedCounter is Counter {
    function incrementBy(uint256 _value) external {
        for (uint256 i = 0; i < _value; i++) {
            increment();
        }
    }
}
```

#### 7.2.2 Libraries and Using For

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

library MathLib {
    function square(uint256 _a) internal pure returns (uint256) {
        return _a * _a;
    }
}

contract MathContract {
    using MathLib for uint256;

    function calculateSquare(uint256 _number) public pure returns (uint256) {
        return _number.square();
    }
}
```

#### 7.2.3 Events and Indexed Parameters

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract EventExample {
    event Transfer(address indexed from, address indexed to, uint256 amount);

    function transfer(address _to, uint256 _amount) public {
        // Transfer logic here
        emit Transfer(msg.sender, _to, _amount);
    }
}
```

### 8. Foundry Commands and Usage 🖥️

#### 8.1 Forge Commands

* **forge build:** Compile all contracts in the project
* **forge test:** Run all tests in the project
* **forge create:** Deploy a contract
* **forge verify-contract:** Verify a deployed contract on Etherscan

#### 8.2 Cast Commands

* **cast call:** Perform a call to a contract without publishing a transaction
* **cast send:** Send a transaction to a contract
* **cast estimate:** Estimate the gas cost of a transaction

#### 8.3 Anvil Commands

* **anvil:** Start a local Ethereum node
* **anvil --fork-url:** Start a node that forks from a specified network

#### 8.4 Verbosity Levels in Foundry Commands

Foundry commands support different verbosity levels, which can be very useful for debugging and getting more detailed information about your operations. These levels are:

* **-v:** Displays basic logs and errors
* **-vv:** Shows more detailed logs, including emitted events
* **-vvv:** Provides even more information, including gas usage for each call
* **-vvvv:** Offers the most detailed output, including stack traces for errors

Example usage:

```bash
forge test -vv
forge create --rpc-url &lt;your_rpc_url&gt; -vvv
```

These verbosity levels can be applied to most Foundry commands, allowing you to tailor the output to your specific needs during development, testing, and deployment processes.

### 9. Real-world Examples 🌍

#### 9.1 DEX (Decentralized Exchange) Smart Contract

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

contract SimpleDEX {
    mapping(address => mapping(address => uint256)) public tokenBalances;

    event Deposit(address user, address token, uint256 amount);
    event Withdraw(address user, address token, uint256 amount);
    event Trade(address user, address tokenGive, uint256 amountGive, address tokenGet, uint256 amountGet);

    function deposit(address _token, uint256 _amount) external {
        require(IERC20(_token).transferFrom(msg.sender, address(this), _amount), "Transfer failed");
        tokenBalances[msg.sender][_token] += _amount;
        emit Deposit(msg.sender, _token, _amount);
    }

    function withdraw(address _token, uint256 _amount) external {
        require(tokenBalances[msg.sender][_token] >= _amount, "Insufficient balance");
        tokenBalances[msg.sender][_token] -= _amount;
        require(IERC20(_token).transfer(msg.sender, _amount), "Transfer failed");
        emit Withdraw(msg.sender, _token, _amount);
    }

    function trade(address _tokenGive, uint256 _amountGive, address _tokenGet, uint256 _amountGet) external {
        require(tokenBalances[msg.sender][_tokenGive] >= _amountGive, "Insufficient balance");
        require(tokenBalances[address(this)][_tokenGet] >= _amountGet, "Insufficient liquidity");

        tokenBalances[msg.sender][_tokenGive] -= _amountGive;
        tokenBalances[address(this)][_tokenGive] += _amountGive;
        tokenBalances[msg.sender][_tokenGet] += _amountGet;
        tokenBalances[address(this)][_tokenGet] -= _amountGet;

        emit Trade(msg.sender, _tokenGive, _amountGive, _tokenGet, _amountGet);
    }
}
```

### 10. Benefits of Using Foundry 🚀

* Faster development cycle
* Improved testing capabilities
* Better debugging tools
* Gas optimization features
* Seamless integration with existing Solidity projects

### 11. Core-level Engineering Concepts 🔬

#### 11.1 Gas Optimization

Gas optimization is crucial in Ethereum development. Here's an example of how to optimize gas usage:

```solidity
// Gas-inefficient
function sumArray(uint256[] memory numbers) public pure returns (uint256) {
    uint256 sum = 0;
    for (uint256 i = 0; i < numbers.length; i++) {
        sum += numbers[i];
    }
    return sum;
}

// Gas-optimized
function sumArrayOptimized(uint256[] memory numbers) public pure returns (uint256) {
    uint256 sum = 0;
    uint256 length = numbers.length;
    for (uint256 i = 0; i < length; i++) {
        sum += numbers[i];
    }
    return sum;
}
```

#### 11.2 Memory vs Storage

Understanding the difference between memory and storage is crucial for efficient smart contract development:

```solidity
contract MemoryVsStorage {
    uint256[] public myArray;

    // Uses storage - modifies the state
    function addToArray(uint256 _number) public {
        myArray.push(_number);
    }

    // Uses memory - doesn't modify the state
    function getArraySum() public view returns (uint256) {
        uint256[] memory tempArray = myArray;
        uint256 sum = 0;
        for (uint256 i = 0; i < tempArray.length; i++) {
            sum += tempArray[i];
        }
        return sum;
    }
}
```
