---
# System prepended metadata

title: Foundry 筆記

---

# Foundry 筆記

## 🧔‍♂️ 資料來源
[Getting Started With Forge
](https://w.mirror.xyz/mOUlpgkWA178HNUW7xR20TdbGRV6dMid7uChqxf9Z58)

## 🧔‍♂️ 首先需要先安裝 Foundry （mac）
``....需要補齊，找一天來重做一次``
- homebrew
- brew install libusb  (若是有跳出 dyld: Library not loaded)
- 安裝 Foundry
```
curl -L https://foundry.paradigm.xyz | bash
source /Users/beard/.zshrc   # 重啟終端機
foundryup
```

## 🧔‍♂️ 建立專案
```
forge init [project name]
cd [project name]
```
<br/><br/>
## 🧔‍♂️ 開始進行測試吧！
### 前提
需要注意幾個事項：
    - 測試檔案放置於 /test 中
    - 檔案命名會為 xxxx.t.sol
    - 需要測試的 function 需要以 test 當成前綴詞命名
        ![](https://i.imgur.com/b6sD1rf.png)
<br/><br/>
### 印出文字/資訊
測試中可以利用 emit log 來印出相關的資訊，也需要依照格式呼叫相對應的 function
![](https://i.imgur.com/IF2yK1C.png)
<br/><br/>
### 開始測試

進行測試，可以在後續的參數增加 [-v ~ -vvvvv]
```
forge script script/Counter.s.sol [-v][-vv][-vvv][-vvvv][-vvvvv]
```

 - -v : 預設模式，一般來說的錯誤顯示
 - -vv : 印出 log
 - -vvv : 印出 [錯誤]測試的追蹤
 - -vvvv : 印出測試的狀態追蹤，若是有[錯誤]測試會顯示相關設定
 - -vvvvv : 印出所有測試的相關設定
<br/><br/>
### 模糊測試 (Fuzzing)
Foundry 測試時，遇到需要傳入的資訊，他會自動依照格式塞入隨機資訊進行測試，並且計算 gas 花費的資訊，以及平均使用值

![](https://i.imgur.com/N28n82F.png)
- runs：代表此 function 測試運作 256 次
- μ：平均 gas 花費 27387
- ~：gas 中位數為 28320
<br/><br/>
### 強制重新 Compile
若是 Foundry 發現您沒有修改調整 Code, 他則會直接利用原本的Compile file直接在運作，而不會重新 Compile。 若是在修改無進行測試的相關程式後，需要重新Compile，則要使用參數 --fouce

```
forge test --force
```
<br/><br/>
### 作弊碼 （Cheat Codes）
作弊碼可以達到超乎想像的操作，偽裝錢包地址....可查看 [forge](https://github.com/foundry-rs/foundry/tree/master/forge)

- 模擬轉到mainnet （利用到 infura ）
<code>vm.createSelectFork("https://mainnet.infura.io/v3/34578ae15.....83");</code>
- 轉成錢包(*address*)的擁有者
<code>vm.prank(*address*);</code>
- 直接給 address(0x1) 10,000顆eth
<code>vm.deal(address(0x1), 10000 ether);</code>

<br/><br/>
### 安裝相依套件
若是需要使用 [ERC721Psi](https://github.com/estarriolvetch/ERC721Psi)，可以利用以下指令進行安裝：

```
forge install estarriolvetch/ERC721Psi
```
- 名稱 （estarriolvetch/ERC721Psi） 為 githob repo name
<br/><br/>

### 重新映射（Remappings）
部分合約是使用類似 NPM 的引入方式（@開頭），這時候則需要設定檔案對應，否則會取得不到。
以下利用 Openzeppelin ERC20 為案例

1. 【套件安裝】首先進行套件安裝：
    ```
    forge install OpenZeppelin/openzeppelin-contracts
    ```

2. 【建立合約程式】在 src 資料夾中，建立 Mytoken.sol，並建立最簡單的 ERC20 範例合約（如下）
    ```
    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.0;

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

    contract Mytoken is ERC20 {
        constructor(uint256 initialSupply) ERC20("MyToken", "MT") {
            _mint(msg.sender, initialSupply);
        }
    }
    ```
3. 【建立測試檔案】在 test 資料夾中，建立 Mytoken.t.sol，並寫入測試的程式。
    ```
    // SPDX-License-Identifier: UNLICENSED
    pragma solidity ^0.8.13;

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

    contract MytokenTest is Test {
        Mytoken public mytoken;
        function setUp() public {
           mytoken = new Mytoken(30000);
        }


        function testlog() public  {
            console.log(mytoken.totalSupply());
        }
    }

    ```
4. 【！進行編譯異常】若是此時直接進行測試編譯，會發現錯誤
    ```
    forge test --force
    ```
    會顯示出以下錯誤 - 找不到匯入的套件檔案：
    ![](https://i.imgur.com/LSTgSEy.png)
    

5. 此時需要進行映射（檔案對應），需要在 forge 專案目錄下建立：remappings.txt，內容新增如下，將 @openzeppelin 對應到 lib路徑中
    ```
    @openzeppelin/=lib/openzeppelin-contracts/ 
    ```
    
    檔案位置參考如下：
    ![](https://i.imgur.com/Ha78Hse.png)


## 🧔‍♂️ 進階用法

### 匹配標誌 (Matching flag)

如果只想測試部分的測試，可以利用參數： -m *string* 進行，會找出名稱中有 *string* 的function 進行測試。

例如。運行 ```forge test -vvvv -m Revert``` 並且函數名稱中帶有 ```"Revert"```的測試都會運行！

### 快照 (snapshot)

可以測試查看gas的耗費狀況 -- *目前版本看來已經內建顯示 gas 耗費*

### 分岔模式(forking mode)

可以模擬真實鏈上的數據進行測試， 只要輸入 ``forge test -f <uri>``. (URI 可以從 Alchemy 或是 Infura的服務中取得)，這樣可以模擬出真正鏈上的回傳跟處理狀況的回應，並獲得實時網絡狀態的響應。這可以使用於難以模擬的合約或狀態進行測試。



###### tags: 開發/閱讀筆記