### Define Governance Event and Setup Constant Source: https://book.getrecon.xyz/print.html Example of a Solidity event definition for proposal creation and the corresponding constant in a Setup.sol file that will be dynamically replaced during fuzzing. ```Solidity event ProposalCreated( uint256 indexed proposalId, address proposer, uint256 newParameter ); uint256 constant TARGET_PARAMETER = 100; ``` -------------------------------- ### CryticToFoundry Contract Integration Source: https://book.getrecon.xyz/print.html Demonstrates how the CryticToFoundry contract inherits the setup function for testing with Foundry, Halmos, and Kontrol. It calls the setup function within its setUp method. ```solidity contract CryticToFoundry is Test, TargetFunctions, FoundryAsserts { function setUp() public { setup(); } } ``` -------------------------------- ### Configuring Setup for Fuzzing Source: https://book.getrecon.xyz/print.html Adjusting the initial minting amount during the setup phase to prevent overflow scenarios in test environments. ```solidity function setup() internal virtual override { ... _finalizeAssetDeployment(_getActors(), approvalArray, type(uint256).max); } ``` -------------------------------- ### Initialize Testing Setup Source: https://book.getrecon.xyz/bootcamp/bootcamp_part_1.html An abstract setup contract that initializes the Morpho protocol along with necessary mocks and asset management utilities for a testing environment. ```solidity abstract contract Setup is BaseSetup, ActorManager, AssetManager, Utils { Morpho morpho; // Mocks MockIRM irm; OracleMock oracle; /// === Setup === /// function setup() internal virtual override { // Deploy Morpho morpho = new Morpho(_getActor()); // Deploy Mocks irm = new MockIRM(); oracle = new OracleMock(); // Deploy assets _newAsset(18); // asset _newAsset(18); // liability } } ``` -------------------------------- ### Install Chimera using Forge Source: https://book.getrecon.xyz/oss/chimera.html This command installs the Chimera framework using the Forge package manager. It's a prerequisite for using Chimera in your smart contract testing setup. ```bash forge install Recon-Fuzz/chimera ``` -------------------------------- ### Setup Contract for Morpho Deployment and Mocks Source: https://book.getrecon.xyz/print.html The `Setup` contract orchestrates the deployment of Morpho, mock IRM, and mock Oracle contracts. It utilizes `AssetManager` and `ActorManager` to manage assets and actors, ensuring a standardized setup process for testing and development. ```solidity abstract contract Setup is BaseSetup, ActorManager, AssetManager, Utils { Morpho morpho; // Mocks MockIRM irm; OracleMock oracle; /// === Setup === /// function setup() internal virtual override { // Deploy Morpho morpho = new Morpho(_getActor()); // Deploy Mocks irm = new MockIRM(); oracle = new OracleMock(); // Deploy assets _newAsset(18); // asset _newAsset(18); // liability } } ``` -------------------------------- ### Install abi-to-mock using npm Source: https://book.getrecon.xyz/oss/abi_to_mock.html Installs the abi-to-mock package globally or locally in your project using npm. This is the first step to using the tool. ```bash npm install abi-to-mock ``` -------------------------------- ### Implementing Morpho Setup Function Source: https://book.getrecon.xyz/print.html Initializes the Morpho contract, mocks, and assets, then creates a market using the specified parameters. ```solidity function setup() internal virtual override { morpho = new Morpho(_getActor()); irm = new MockIRM(); oracle = new OracleMock(); _newAsset(18); // asset _newAsset(18); // liability morpho.enableIrm(address(irm)); morpho.enableIrm(address(irm)); morpho.enableLltv(8e17); address[] memory assets = _getAssets(); MarketParams memory marketParams = MarketParams({ loanToken: assets[1], collateralToken: assets[0], oracle: address(oracle), irm: address(irm), lltv: 8e17 }); morpho.createMarket(marketParams); } ``` -------------------------------- ### Setup Contract for Morpho Deployment - Solidity Source: https://book.getrecon.xyz/bootcamp/bootcamp_part_1.html This Solidity abstract contract 'Setup' inherits from BaseSetup, ActorManager, and AssetManager. It defines a 'morpho' state variable and implements the 'setup' function to deploy the Morpho contract, passing '_getActor()' as the owner. This contract is designed to be inherited for fuzz testing. ```solidity __ abstract contract Setup is BaseSetup, ActorManager, AssetManager, Utils { Morpho morpho; function setup() internal virtual override { morpho = new Morpho(_getActor()); } ... } ``` -------------------------------- ### Log Parser - Installation Source: https://book.getrecon.xyz/print.html Install the Log Parser package using Yarn. ```APIDOC ## Log Parser - Installation ### Description Install the Log Parser package using Yarn. ### Method `shell` ### Endpoint N/A ### Parameters N/A ### Request Example ```bash yarn add @recon-fuzz/log-parser ``` ### Response N/A ``` -------------------------------- ### Setup Contract for Morpho Deployment Source: https://book.getrecon.xyz/print.html Illustrates how the Setup contract deploys the Morpho contract, passing the current actor's address as the owner. This simplifies the deployment process within the testing framework. ```solidity abstract contract Setup is BaseSetup, ActorManager, AssetManager, Utils { Morpho morpho; function setup() internal virtual override { morpho = new Morpho(_getActor()); } ... } ``` -------------------------------- ### Install Recon Dependencies Source: https://book.getrecon.xyz/using_recon/building_handlers.html Command to install the required Chimera and setup-helpers libraries into a Foundry project using forge. ```Bash forge install Recon-Fuzz/chimera Recon-Fuzz/setup-helpers --no-commit ``` -------------------------------- ### Register Morpho Market and Dependencies Source: https://book.getrecon.xyz/bootcamp/bootcamp_part_1.html Imports necessary structs and demonstrates the setup function to deploy the Morpho contract, mock IRM/Oracle, and create a new market. ```Solidity import {Morpho, MarketParams} from "src/Morpho.sol"; function setup() internal virtual override { morpho = new Morpho(_getActor()); irm = new MockIRM(); oracle = new OracleMock(); _newAsset(18); _newAsset(18); morpho.enableIrm(address(irm)); morpho.enableLltv(8e17); address[] memory assets = _getAssets(); MarketParams memory marketParams = MarketParams({ loanToken: assets[1], collateralToken: assets[0], oracle: address(oracle), irm: address(irm), lltv: 8e17 }); morpho.createMarket(marketParams); } ``` -------------------------------- ### Setup Contract for Deploying Target Contracts (Solidity) Source: https://book.getrecon.xyz/writing_invariant_tests/chimera_framework.html An abstract contract 'Setup' that inherits from 'BaseSetup'. It is responsible for deploying and initializing the state of target contracts, such as 'Counter', before fuzzing begins. This contract serves as a central point for setting up the testing environment. ```solidity abstract contract Setup is BaseSetup { Counter counter; function setup() internal virtual override { counter = new Counter(); } } ``` -------------------------------- ### Install and Use Log Parser Source: https://book.getrecon.xyz/print.html Installation instructions and basic usage for the @recon-fuzz/log-parser package to process fuzzer logs. ```bash yarn add @recon-fuzz/log-parser ``` ```typescript import { processLogs, Fuzzer } from '@recon-fuzz/log-parser'; const medusaResults = processLogs(medusaLogContent, Fuzzer.MEDUSA); const echidnaResults = processLogs(echidnaLogContent, Fuzzer.ECHIDNA); ``` -------------------------------- ### Run Medusa Fuzz Tests Source: https://book.getrecon.xyz/writing_invariant_tests/chimera_framework.html Command to start fuzzing with Medusa. This is a straightforward command that initiates the fuzzing process. Ensure Medusa is installed and configured. ```shell medusa fuzz ``` -------------------------------- ### CryticToFoundry Contract for Foundry/Halmos/Kontrol - Solidity Source: https://book.getrecon.xyz/bootcamp/bootcamp_part_1.html The CryticToFoundry contract inherits from Test, TargetFunctions, and FoundryAsserts. The 'setUp' function calls 'setup()', allowing it to be tested with Foundry, Halmos, and Kontrol. This highlights the Chimera Framework's benefit of cross-tool compatibility. ```solidity __ contract CryticToFoundry is Test, TargetFunctions, FoundryAsserts { function setUp() public { setup(); } } ``` -------------------------------- ### Initialize Test Environment Source: https://book.getrecon.xyz/print.html Configures the test setup by initializing the RewardsManager, registering additional actors, and deploying mock ERC20 assets with varying decimal values. ```solidity function setup() internal virtual override { rewardsManager = new RewardsManager(); // Add 3 additional actors (default actor is address(this)) _addActor(address(0x411c3)); _addActor(address(0xb0b)); _addActor(address(0xc0ff3)); // Deploy MockERC20 assets _newAsset(18); _newAsset(8); _newAsset(6); // Mints to all actors and approves allowances to the counter address[] memory approvalArray = new address[](1); approvalArray[0] = address(rewardsManager); _finalizeAssetDeployment(_getActors(), approvalArray, type(uint88).max); } ``` -------------------------------- ### Log Parser - Usage Example Source: https://book.getrecon.xyz/print.html Example of processing Medusa and Echidna logs using the Log Parser. ```APIDOC ## Log Parser - Usage Example ### Description Example of processing Medusa and Echidna logs using the Log Parser. ### Method `typescript` ### Endpoint N/A ### Parameters N/A ### Request Example ```typescript import { processLogs, Fuzzer } from '@recon-fuzz/log-parser'; // Process Medusa logs const medusaResults = processLogs(medusaLogContent, Fuzzer.MEDUSA); // Process Echidna logs const echidnaResults = processLogs(echidnaLogContent, Fuzzer.ECHIDNA); ``` ### Response N/A ``` -------------------------------- ### CryticTester Contract Integration Source: https://book.getrecon.xyz/print.html Shows how the CryticTester contract inherits the setup function to deploy contracts, enabling testing with Echidna or Medusa. It calls the setup function within its constructor. ```solidity contract CryticTester is TargetFunctions, CryticAsserts { constructor() payable { setup(); } } ``` -------------------------------- ### Example Setup.sol Constant for Parameter Replacement Source: https://book.getrecon.xyz/using_recon/governance_fuzzing.html This snippet demonstrates a constant within a Setup.sol file that can be dynamically updated by Governance Fuzzing. The 'XX' placeholder will be replaced with values from detected on-chain events. ```solidity uint256 constant TARGET_PARAMETER = 100; ``` -------------------------------- ### Install ERC7540 Reusable Properties with Foundry Source: https://book.getrecon.xyz/oss/erc7540.html Installs the `erc7540-reusable-properties` library as a dependency into a Foundry project using the `forge install` command. This is the first step to integrating the reusable properties into your smart contracts. ```bash forge install Recon-Fuzz/erc7540-reusable-properties --no-commit ``` -------------------------------- ### Configure Setup Contract Source: https://book.getrecon.xyz/writing_invariant_tests/example_project.html An abstract setup contract that manages asset deployment and actor permissions for invariant testing. It integrates with AssetManager and ActorManager to prepare the environment for the Points contract. ```solidity abstract contract Setup is BaseSetup, ActorManager, AssetManager, Utils { Points points; /// === Setup === /// function setup() internal virtual override { _newAsset(18); // deploys an 18 decimal token // Deploy Points contract points = new Points(_getAsset()); // uses the asset deployed above and managed by the AssetManager // Mints the deployed asset to all actors and sets max allowances for the points contract address[] memory approvalArray = new address[](1); approvalArray[0] = address(points); _finalizeAssetDeployment(_getActors(), approvalArray, type(uint256).max); } /// === MODIFIERS === /// modifier asAdmin { vm.prank(address(this)); _; } modifier asActor { vm.prank(address(_getActor())); _; } } ``` -------------------------------- ### Implement Actor Switching for ERC7540Properties Source: https://book.getrecon.xyz/print.html Provides an example implementation for the `setup_switchActor` function within an ERC7540Properties-based contract. This function enables dynamic switching of the 'actor' state variable, which is essential for testing different actor roles in your system. ```Solidity function setup_switchActor(uint8 actorIndex) public { actor = actorsArray[actorIndex % actorsArray.length]; } ``` -------------------------------- ### Example Parameter Replacement Configuration Source: https://book.getrecon.xyz/using_recon/governance_fuzzing.html This example shows how to configure the parameter replacement in Recon's Governance Fuzzing UI. It maps the 'newParameter' from the 'ProposalCreated' event to update the 'TARGET_PARAMETER' constant in Setup.sol. ```text uint256 constant TARGET_PARAMETER = uint256(XX); ``` -------------------------------- ### Setup Assets and Approvals in Solidity Source: https://book.getrecon.xyz/print.html This function iterates through system assets to mint tokens to actors and approve the Morpho contract to spend them. It uses a large constant value to facilitate overflow testing and handles multiple actors to ensure proper system state. ```solidity function _setupAssetsAndApprovals() internal { address[] memory actors = _getActors(); uint256 amount = type(uint88).max; for (uint256 assetIndex = 0; assetIndex < _getAssets().length; assetIndex++) { address asset = _getAssets()[assetIndex]; for (uint256 i = 0; i < actors.length; i++) { vm.prank(actors[i]); MockERC20(asset).mint(actors[i], amount); } for (uint256 i = 0; i < actors.length; i++) { vm.prank(actors[i]); MockERC20(asset).approve(address(morpho), type(uint88).max); } } } ``` -------------------------------- ### Initial Asset Minting in Setup Function Source: https://book.getrecon.xyz/writing_invariant_tests/example_project.html This code from the `setup` function reveals that `type(uint256).max` is initially minted to actors, providing them with a large amount of assets that can lead to overflows when deposited into `uint88` variables. ```solidity function setup() internal virtual override { ... _finalizeAssetDeployment(_getActors(), approvalArray, type(uint256).max); } ``` -------------------------------- ### Implementing Global Invariants and Boolean Properties Source: https://book.getrecon.xyz/print.html Examples of global properties that can be checked after any state-changing operation. It demonstrates both assertion-based invariants and boolean-based property functions. ```Solidity function invariant_number_never_zero() public { gt(counter.number(), 0, "number is zero"); } function echidna_number_never_zero() public returns (bool) { return counter.number() == 0; } ``` -------------------------------- ### Optimizing Target Functions with Storage Variables Source: https://book.getrecon.xyz/print.html Stores market parameters in a storage variable within the setup contract to allow target functions to access them directly, reducing fuzzer input complexity. ```solidity abstract contract Setup is BaseSetup, ActorManager, AssetManager, Utils { MarketParams marketParams; function setup() internal virtual override { address[] memory assets = _getAssets(); marketParams = MarketParams({ loanToken: assets[1], collateralToken: assets[0], oracle: address(oracle), irm: address(irm), lltv: 8e17 }); morpho.createMarket(marketParams); } } abstract contract MorphoTargets is BaseTargetFunctions, Properties { function morpho_accrueInterest() public asActor { morpho.accrueInterest(marketParams); } function morpho_borrow(uint256 assets, uint256 shares, address onBehalf, address receiver) public asActor { morpho.borrow(marketParams, assets, shares, onBehalf, receiver); } function morpho_createMarket() public asActor { morpho.createMarket(marketParams); } } ``` -------------------------------- ### Optimize Fuzzer Coverage with Storage Variables Source: https://book.getrecon.xyz/bootcamp/bootcamp_part_1.html Stores MarketParams as a storage variable in the setup contract to simplify target function signatures and improve fuzzer efficiency by clamping inputs. ```Solidity abstract contract Setup is BaseSetup, ActorManager, AssetManager, Utils { MarketParams marketParams; function setup() internal virtual override { address[] memory assets = _getAssets(); marketParams = MarketParams({ loanToken: assets[1], collateralToken: assets[0], oracle: address(oracle), irm: address(irm), lltv: 8e17 }); morpho.createMarket(marketParams); } } abstract contract MorphoTargets is BaseTargetFunctions, Properties { function morpho_accrueInterest() public asActor { morpho.accrueInterest(marketParams); } function morpho_borrow(uint256 assets, uint256 shares, address onBehalf, address receiver) public asActor { morpho.borrow(marketParams, assets, shares, onBehalf, receiver); } } ``` -------------------------------- ### CryticTester Contract for Echidna/Medusa - Solidity Source: https://book.getrecon.xyz/bootcamp/bootcamp_part_1.html The CryticTester contract inherits from TargetFunctions and CryticAsserts. Its constructor calls the 'setup' function, enabling it to be used with fuzzers like Echidna and Medusa. This demonstrates how a single setup can be reused across different testing tools. ```solidity __ contract CryticTester is TargetFunctions, CryticAsserts { constructor() payable { setup(); } } ``` -------------------------------- ### Setup Assets and Approvals for Morpho Source: https://book.getrecon.xyz/bootcamp/bootcamp_part_1.html This function iterates through system assets to mint tokens to actors and grant the Morpho contract approval to spend them. It uses a large constant (type(uint88).max) to facilitate overflow testing. ```solidity function _setupAssetsAndApprovals() internal { address[] memory actors = _getActors(); uint256 amount = type(uint88).max; for (uint256 assetIndex = 0; assetIndex < _getAssets().length; assetIndex++) { address asset = _getAssets()[assetIndex]; for (uint256 i = 0; i < actors.length; i++) { vm.prank(actors[i]); MockERC20(asset).mint(actors[i], amount); } for (uint256 i = 0; i < actors.length; i++) { vm.prank(actors[i]); MockERC20(asset).approve(address(morpho), type(uint88).max); } } } ``` -------------------------------- ### Dynamic Market Configuration for Fuzzing Source: https://book.getrecon.xyz/bootcamp/bootcamp_part_2.html Replaces static market setup with dynamic functions that accept fuzzed inputs. This allows the fuzzer to explore a wider range of market configurations and edge cases. ```solidity function morpho_createMarket_clamped(uint8 index, uint256 lltv) public { address loanToken = _getAssets()[index % _getAssets().length]; address collateralToken = _getAsset(); marketParams = MarketParams({ loanToken: loanToken, collateralToken: collateralToken, oracle: address(oracle), irm: address(irm), lltv: lltv }); morpho_createMarket(marketParams); } function morpho_createMarket(MarketParams memory _marketParams) public asActor { morpho.createMarket(_marketParams); } ``` -------------------------------- ### Handle Errors in Fuzzing Tests Source: https://book.getrecon.xyz/oss/setup_helpers.html Demonstrates how to use the checkError utility within a target function to validate expected revert reasons, including require strings, custom errors, and compiler panics. ```Solidity function counter_setNumber(uint256 newNumber) public updateGhosts asActor { try counter.setNumber(newNumber) { // passes } catch (bytes memory err) { bool expectedError; // checks for custom errors and panics expectedError = checkError(err, "abc") || // error string from require statement checkError(err, "CustomError()") || // custom error checkError(err, Panic.arithmeticPanic); // compiler panic errors t(expectedError, "unexpected error"); } } ``` -------------------------------- ### Implement Actor Switching Functionality Source: https://book.getrecon.xyz/oss/erc7540.html Provides an example implementation for a function that changes the `actor` state variable within the `ERC7540Properties` contract. This function, `setup_switchActor`, allows cycling through an array of actors based on an index, ensuring the `actor` is always valid. ```solidity function setup_switchActor(uint8 actorIndex) public { actor = actorsArray[actorIndex % actorsArray.length]; } ``` -------------------------------- ### Initialize Chimera Project Source: https://book.getrecon.xyz/writing_invariant_tests/example_project.html Commands to initialize a new project using the Create Chimera App template. Requires Foundry to be installed on the local machine. ```bash forge init --template https://github.com/Recon-Fuzz/create-chimera-app-no-boilerplate ``` -------------------------------- ### Deploy Morpho Contract with Owner - Solidity Source: https://book.getrecon.xyz/bootcamp/bootcamp_part_1.html This Solidity code snippet shows the constructor for the Morpho contract, which requires an owner address. It initializes the DOMAIN_SEPARATOR and sets the owner, emitting a SetOwner event. This is used to determine the deployment parameters for the Setup contract. ```solidity __ contract Morpho is IMorphoStaticTyping { ... /// @param newOwner The new owner of the contract. constructor(address newOwner) { require(newOwner != address(0), ErrorsLib.ZERO_ADDRESS); DOMAIN_SEPARATOR = keccak256(abi.encode(DOMAIN_TYPEHASH, block.chainid, address(this))); owner = newOwner; emit EventsLib.SetOwner(newOwner); } ... } ```