-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add automated toolings for testing contracts (#151)
* Add Slither support in GH actions * Add slither-mutate support for local execution * Add readme for test directory * Fix rebasing with development * Add Echidna support for local execution * Fix spelling typo
- Loading branch information
Showing
20 changed files
with
216 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,7 @@ on: | |
|
||
permissions: | ||
contents: read | ||
security-events: write | ||
|
||
env: | ||
FOUNDRY_PROFILE: ci | ||
|
@@ -29,21 +30,10 @@ jobs: | |
with: | ||
submodules: recursive | ||
|
||
#- name: Install Foundry | ||
# uses: foundry-rs/foundry-toolchain@v1 | ||
# with: | ||
# version: nightly | ||
|
||
- uses: actions/checkout@v4 | ||
- name: Install Foundry | ||
uses: foundry-rs/foundry-toolchain@v1 | ||
with: | ||
repository: foundry-rs/foundry | ||
path: ./foundry | ||
submodules: recursive | ||
ref: 5ac78a9cd4b94dc53d1fe5e0f42372b28b5a7559 | ||
|
||
- name: Install Forge | ||
run: | | ||
cargo install --path ./foundry/crates/forge --profile local --force --locked | ||
version: nightly | ||
|
||
- name: Check formatting | ||
if: ${{ contains(matrix.system.os, 'windows') == false }} | ||
|
@@ -61,3 +51,19 @@ jobs: | |
run: | | ||
forge test -vvv | ||
id: test | ||
|
||
- name: Run Slither | ||
if: ${{ contains(matrix.system.os, 'ubuntu') == true }} | ||
uses: crytic/[email protected] | ||
with: | ||
solc-version: 0.8.23 | ||
sarif: results.sarif | ||
fail-on: none | ||
slither-args: --exclude-dependencies --exclude-low --exclude-informational --filter-paths "Ed25519.sol" | ||
id: slither | ||
|
||
- name: Upload SARIF file | ||
if: ${{ contains(matrix.system.os, 'ubuntu') == true }} | ||
uses: github/codeql-action/upload-sarif@v3 | ||
with: | ||
sarif_file: ${{ steps.slither.outputs.sarif }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Submodule properties
added at
bb1b78
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
# Testing Smart Contracts with Foundry and Other Frameworks | ||
|
||
This repository utilizes the Foundry and other frameworks for testing smart contracts. Within the `test` directory, you will find multiple script files designed to be executed locally. These scripts are integral for different testing and analysis tools: `Slither`, `slither-mutate`, and `Echidna`. Below is an overview of each script and the respective tools they utilize. | ||
|
||
## Overview of Scripts | ||
|
||
1. **Slither Script** | ||
- **Script File:** `scripts/runSlither.sh` | ||
- **Purpose:** This script runs the `Slither` tool, which is used for static analysis of smart contracts. | ||
- **Details:** `Slither` helps in identifying potential vulnerabilities and issues in the smart contract code without executing it. It provides insights into security, correctness, and gas optimization. | ||
|
||
2. **Slither-Mutate Script** | ||
- **Script File:** `scripts/runSlitherMutate.sh` | ||
- **Purpose:** This script executes the `slither-mutate` tool, which extends `Slither`’s capabilities by introducing mutation testing. | ||
- **Details:** `Slither-mutate` creates variations (mutants) of the smart contract code to check if the existing test cases can detect these mutations. It helps in assessing the effectiveness and coverage of the test suite. | ||
|
||
3. **Echidna Script** | ||
- **Script File:** `scripts/runEchidna.sh` | ||
- **Purpose:** This script runs the `Echidna` tool, a property-based fuzzer. | ||
- **Details:** `Echidna`is used to find bugs by generating random inputs to test the smart contract properties. It helps in uncovering edge cases and ensuring that the contracts behave as expected under various conditions. | ||
|
||
## Tools Overview | ||
|
||
### Slither | ||
|
||
`Slither` is a static analysis framework specifically designed for smart contracts. It analyzes the contract code without executing it, providing valuable insights into: | ||
- Security vulnerabilities | ||
- Code correctness | ||
- Optimization opportunities | ||
- Compliance with best practices | ||
|
||
### Slither-Mutate | ||
|
||
`Slither-mutate` leverages the static analysis power of `Slither` and combines it with mutation testing. By creating and testing mutated versions of the contract, it evaluates: | ||
- The robustness of the existing test cases | ||
- The overall test coverage | ||
- The ability of the tests to detect potential issues | ||
|
||
### Echidna | ||
|
||
`Echidna` is a property-based testing tool (fuzzer) for smart contracts. It works by: | ||
- Generating random inputs to interact with the smart contract | ||
- Checking predefined properties and invariants | ||
- Identifying unexpected behavior or bugs | ||
|
||
To get familiar with `Echinida` tool, you can refer to the Secure Contracts website and follow [Echidna tutorial](https://secure-contracts.com/program-analysis/echidna/index.html). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
pragma solidity 0.8.23; | ||
|
||
import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; | ||
import { PropertiesAsserts } from "properties/util/PropertiesHelper.sol"; | ||
import { L2LiskToken } from "src/L2/L2LiskToken.sol"; | ||
import { L2LockingPosition } from "src/L2/L2LockingPosition.sol"; | ||
import { L2Staking } from "src/L2/L2Staking.sol"; | ||
|
||
interface iHevm { | ||
function prank(address sender) external; | ||
} | ||
|
||
contract L2RewardEchidnaTest is PropertiesAsserts { | ||
L2Staking public l2Staking; | ||
L2LockingPosition public l2LockingPosition; | ||
|
||
iHevm public hevm; | ||
|
||
constructor() { | ||
hevm = iHevm(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D); | ||
address bridge = address(0x1234567890123456789012345678901234567890); | ||
address remoteToken = address(0xaBcDef1234567890123456789012345678901234); | ||
|
||
hevm.prank(msg.sender); | ||
L2LiskToken l2LiskToken = new L2LiskToken(remoteToken); | ||
l2LiskToken.initialize(bridge); | ||
|
||
L2Staking l2StakingImplementation = new L2Staking(); | ||
l2Staking = L2Staking( | ||
address( | ||
new ERC1967Proxy( | ||
address(l2StakingImplementation), | ||
abi.encodeWithSelector(l2Staking.initialize.selector, address(l2LiskToken)) | ||
) | ||
) | ||
); | ||
|
||
L2LockingPosition l2LockingPositionImplementation = new L2LockingPosition(); | ||
l2LockingPosition = L2LockingPosition( | ||
address( | ||
new ERC1967Proxy( | ||
address(l2LockingPositionImplementation), | ||
abi.encodeWithSelector(l2LockingPosition.initialize.selector, address(l2Staking)) | ||
) | ||
) | ||
); | ||
} | ||
|
||
function durationIsNeverLargerThanMax(uint256 lockID) public { | ||
lockID = PropertiesAsserts.clampBetween(lockID, 1, 1000); | ||
(,, uint256 expDate, uint256 pausedDuration) = l2LockingPosition.lockingPositions(lockID); | ||
uint256 maxDuration = l2Staking.MAX_LOCKING_DURATION(); | ||
uint256 today = block.timestamp / 1 days; | ||
PropertiesAsserts.assertWithMsg( | ||
pausedDuration <= maxDuration, "The position paused duration is larger than max!" | ||
); | ||
if (expDate > today) { | ||
PropertiesAsserts.assertWithMsg( | ||
expDate - today <= maxDuration, "The position unpaused duration is larger than max!" | ||
); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
#!/usr/bin/env bash | ||
|
||
echo "Instructing the shell to exit immediately if any command returns a non-zero exit status..." | ||
set -e | ||
echo "Done." | ||
|
||
echo "Navigating to the root directory of the project..." | ||
cd ../../ | ||
echo "Done." | ||
|
||
if [ -z "$1" ] | ||
then | ||
echo "Please provide the contract name as the first argument."$'\n'"Example: runEchidna.sh <contract_name>" | ||
exit 1 | ||
fi | ||
|
||
echo "Starting Echidna tool..." | ||
echidna test/fuzzing --workers 5 --contract $1 --corpus-dir test/fuzzing --format text --test-mode assertion --test-limit 5000000 | ||
echo "Done." |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
#!/usr/bin/env bash | ||
|
||
echo "Instructing the shell to exit immediately if any command returns a non-zero exit status..." | ||
set -e | ||
echo "Done." | ||
|
||
echo "Navigating to the root directory of the project..." | ||
cd ../../ | ||
echo "Done." | ||
|
||
echo "Removing file slitherResults.md if it exists..." | ||
if [ -f "slitherResults.md" ] | ||
then | ||
rm slitherResults.md | ||
fi | ||
echo "Done." | ||
|
||
echo "Starting Slither tool..." | ||
slither . --exclude-dependencies --exclude-low --exclude-informational --filter-paths "Ed25519.sol" --checklist > slitherResults.md | ||
echo "Done." |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
#!/usr/bin/env bash | ||
|
||
echo "Instructing the shell to exit immediately if any command returns a non-zero exit status..." | ||
set -e | ||
echo "Done." | ||
|
||
echo "Navigating to the root directory of the project..." | ||
cd ../../ | ||
echo "Done." | ||
|
||
echo "Removing directory mutation_campaign if it exists..." | ||
if [ -d "mutation_campaign" ] | ||
then | ||
rm -rf mutation_campaign | ||
fi | ||
echo "Done." | ||
|
||
echo "Starting Slither Mutate Campaign..." | ||
slither-mutate . --test-cmd='forge test' --test-dir='test' --ignore-dirs='script,lib,test,utils,cache,out,broadcast,deployment' | ||
echo "Done." |