https://github.com/ArnaudSene/solidity-foundry-training
forge init
In this example we want to use Chainlink llibrary
Chainlink Github: https://github.com/smartcontractkit/chainlink-brownie-contracts
Copy only smartcontractkit/chainlink-brownie-contracts
Choose a version or the latest. We choose 0.6.1
Install the library
forge install smartcontractkit/chainlink-brownie-contracts@0.6.1 --no-commit
You need to create a mapping to get an appropriate path
Edit: foundry.toml
Create a remappings
remappings = ["@chainlink/contracts/=lib/chainlink-brownie-contracts/"]
forge build
[⠢] Compiling...
[⠰] Compiling 3 files with 0.8.21
[⠔] Solc 0.8.21 finished in 80.46ms
Compiler run successful!
Best practice is to name errors
ContractName__ErrorName
error FundMe__NotOwner();
During tests execution
owner
of the contract is the script itself => address(this)
caller
of the contract is us => msg.sender
Tests are executed on a local blockchain. Same as local blockchain ran with Anvil
forge test
forge test -vv
forge test -vvv
forge test --match-test testPriceFeedVersionIsAccurate -vvv
Problem: Contract that have an address hardcoded
With a contract that have an address set inside the contract itself,
this address is dedicated to a chain network (e.g. Sepolia).
By default tests are executed on a local blockchain with Anvil
[⠢] Compiling...
No files changed, compilation skipped
Running 1 test for test/FundMe.t.sol:FundMeTest
[FAIL. Reason: EvmError: Revert] testPriceFeedVersionIsAccurate() (gas: 10113)
Traces:
[10113] FundMeTest::testPriceFeedVersionIsAccurate()
├─ [5099] FundMe::getVersion() [staticcall]
│ ├─ [0] 0x694AA1769357215DE4FAC081bf1f309aDC325306::version() [staticcall]
│ │ └─ ← ()
│ └─ ← EvmError: Revert
└─ ← EvmError: Revert
Test result: FAILED. 0 passed; 1 failed; 0 skipped; finished in 3.52ms
Ran 1 test suites: 0 tests passed, 1 failed, 0 skipped (1 total tests)
Failing tests:
Encountered 1 failing test in test/FundMe.t.sol:FundMeTest
[FAIL. Reason: EvmError: Revert] testPriceFeedVersionIsAccurate() (gas: 10113)
Encountered a total of 1 failing tests, 0 tests succeeded
Solution: Use The appropriate chain Network, in this case Sepolia
Go on Alchemy and retrieve the Sepolia URL.
-> Dashboard -> My Apps -> API key -> HTTPS
Edit the .env file
SEPOLIA_RPC_URL=https://eth-sepolia.g.alchemy.com/v2/<KEY>
source .env
forge test --match-test testPriceFeedVersionIsAccurate -vvv --fork-url $SEPOLIA_RPC_URL
[⠢] Compiling...
No files changed, compilation skipped
Running 1 test for test/FundMe.t.sol:FundMeTest
[PASS] testPriceFeedVersionIsAccurate() (gas: 16139)
Test result: ok. 1 passed; 0 failed; 0 skipped; finished in 1.26s
Ran 1 test suites: 1 tests passed, 0 failed, 0 skipped (1 total tests)
forge coverage --fork-url $SEPOLIA_RPC_URL
⠒] Compiling...
[⠊] Compiling 29 files with 0.8.21
[⠒] Solc 0.8.21 finished in 2.95s
Compiler run successful!
Analysing contracts...
Running tests...
| File | % Lines | % Statements | % Branches | % Funcs |
|---------------------------|---------------|---------------|---------------|---------------|
| script/Counter.s.sol | 0.00% (0/1) | 0.00% (0/1) | 100.00% (0/0) | 0.00% (0/2) |
| script/DeployFundMe.s.sol | 100.00% (4/4) | 100.00% (5/5) | 100.00% (0/0) | 100.00% (1/1) |
| src/Counter.sol | 100.00% (2/2) | 100.00% (2/2) | 100.00% (0/0) | 100.00% (2/2) |
| src/FundMe.sol | 9.09% (1/11) | 13.33% (2/15) | 0.00% (0/4) | 25.00% (1/4) |
| src/PriceConverter.sol | 0.00% (0/6) | 0.00% (0/11) | 100.00% (0/0) | 0.00% (0/2) |
| Total | 29.17% (7/24) | 26.47% (9/34) | 0.00% (0/4) | 36.36% (4/11) |
Executing command forge snapshot
will create a file named gas-snapshot.
forge snapshot --match-test testWithdrawWithASingleFunder
FundMeTest:testWithdrawWithASingleFunder() (gas: 86433)
chisel
Welcome to Chisel! Type `!help` to show available commands.
➜ uint256 cat = 1;
➜ cat
Type: uint
├ Hex: 0x0000000000000000000000000000000000000000000000000000000000000001
└ Decimal: 1
!help
⚒️ Chisel help
=============
General
!help | !h - Display all commands
!quit | !q - Quit Chisel
!exec <command> [args] | !e <command> [args] - Execute a shell command and print the output
Session
!clear | !c - Clear current session source
!source | !so - Display the source code of the current session
!save [id] | !s [id] - Save the current session to cache
!load <id> | !l <id> - Load a previous session ID from cache
!list | !ls - List all cached sessions
!clearcache | !cc - Clear the chisel cache of all stored sessions
!export | !ex - Export the current session source to a script file
!fetch <addr> <name> | !fe <addr> <name> - Fetch the interface of a verified contract on Etherscan
!edit - Open the current session in an editor
Environment
!fork <url> | !f <url> - Fork an RPC for the current session. Supply 0 arguments to return to a local network
!traces | !t - Enable / disable traces for the current session
!calldata [data] | !cd [data] - Set calldata (`msg.data`) for the current session (appended after function selector). Clears it if no argument provided.
Debug
!memdump | !md - Dump the raw memory of the current state
!stackdump | !sd - Dump the raw stack of the current state
!rawstack <var> | !rs <var> - Display the raw value of a variable's stack allocation. For variables that are > 32 bytes in length, this will display their memory pointer.