diff --git a/echidna-config.yaml b/echidna-config.yaml index 6f37dcf0..2cc67130 100644 --- a/echidna-config.yaml +++ b/echidna-config.yaml @@ -1,6 +1,6 @@ workers: 1 testLimit: 50000 -seqLen: 1024 +seqLen: 100 codeSize: 0x9000 @@ -21,7 +21,9 @@ cryticArgs: [ erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/ forge-std/=lib/forge-std/src/ openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/ - openzeppelin-contracts/=lib/openzeppelin-contracts/", + openzeppelin-contracts/=lib/openzeppelin-contracts/ + solady/=lib/solady/ + solarray/=lib/solarray/src/", ] prefix: "invariant_" @@ -33,13 +35,4 @@ corpusDir: echidna-corpus allContracts: false filterBlacklist: false # if false, allows filterFunctions filterFunctions: - [ - "IonPool_Echidna.supply(uint8,uint88,uint48)", - "IonPool_Echidna.withdraw(uint8,uint88,uint48)", - "IonPool_Echidna.borrow(uint8,uint8,uint128,uint48)", - "IonPool_Echidna.repay(uint8,uint8,uint128,uint48)", - "IonPool_Echidna.depositCollateral(uint8,uint8,uint128,uint48)", - "IonPool_Echidna.withdrawCollateral(uint8,uint8,uint128,uint48)", - "IonPool_Echidna.gemJoin(uint8,uint8,uint128,uint48)", - "IonPool_Echidna.gemExit(uint8,uint8,uint128,uint48)", - ] + ["IonPool_Echidna.fuzzedFallback(uint128,uint128,uint128,uint128,uint256)"] diff --git a/foundry.toml b/foundry.toml index 0d983a00..5a4c56ba 100644 --- a/foundry.toml +++ b/foundry.toml @@ -26,7 +26,7 @@ max_test_rejects = 655360 [profile.default.invariant] runs = 20 -depth = 1536 +depth = 100 fail_on_revert = true call_override = false # reentrancy-check preserve_state = true diff --git a/test/helpers/BaseTestSetup.sol b/test/helpers/BaseTestSetup.sol index ad59edf1..4344ad83 100644 --- a/test/helpers/BaseTestSetup.sol +++ b/test/helpers/BaseTestSetup.sol @@ -31,11 +31,5 @@ abstract contract BaseTestSetup is Test { function setUp() public virtual { underlying = new ERC20PresetMinterPauser("WETH", "Wrapped Ether"); - if (address(WETH_ADDRESS).code.length == 0) { - vm.etch(address(WETH_ADDRESS), address(underlying).code); - underlying = ERC20PresetMinterPauser(address(WETH_ADDRESS)); - underlying.grantRole(underlying.MINTER_ROLE(), address(this)); - underlying.grantRole(underlying.DEFAULT_ADMIN_ROLE(), address(this)); - } } } diff --git a/test/invariant/IonPool/IonPoolEchidna.sol b/test/invariant/IonPool/IonPoolEchidna.sol index 741f6d83..527b2757 100644 --- a/test/invariant/IonPool/IonPoolEchidna.sol +++ b/test/invariant/IonPool/IonPoolEchidna.sol @@ -8,36 +8,15 @@ contract IonPool_Echidna is IonPool_InvariantTest { _setUp(false, false); } - // function supply(uint8 index, uint88 amount, uint48 warpTimeAmount) external { - // actorManager.supply(index, amount, warpTimeAmount); - // } - - // function withdraw(uint8 index, uint88 amount, uint48 warpTimeAmount) external { - // actorManager.withdraw(index, amount, warpTimeAmount); - // } - - // function borrow(uint8 borrowerIndex, uint8 ilkIndex, uint128 amount, uint48 warpTimeAmount) external { - // actorManager.borrow(borrowerIndex, ilkIndex, amount, warpTimeAmount); - // } - - // function repay(uint8 borrowerIndex, uint8 ilkIndex, uint128 amount, uint48 warpTimeAmount) external { - // actorManager.repay(borrowerIndex, ilkIndex, amount, warpTimeAmount); - // } - - // function depositCollateral(uint8 borrowerIndex, uint8 ilkIndex, uint128 amount, uint48 warpTimeAmount) external { - // actorManager.depositCollateral(borrowerIndex, ilkIndex, amount, warpTimeAmount); - // } - - // function withdrawCollateral(uint8 borrowerIndex, uint8 ilkIndex, uint128 amount, uint48 warpTimeAmount) external - // { - // actorManager.withdrawCollateral(borrowerIndex, ilkIndex, amount, warpTimeAmount); - // } - - // function gemJoin(uint8 borrowerIndex, uint8 ilkIndex, uint128 amount, uint48 warpTimeAmount) external { - // actorManager.gemJoin(borrowerIndex, ilkIndex, amount, warpTimeAmount); - // } - - // function gemExit(uint8 borrowerIndex, uint8 ilkIndex, uint128 amount, uint48 warpTimeAmount) external { - // actorManager.gemExit(borrowerIndex, ilkIndex, amount, warpTimeAmount); - // } + function fuzzedFallback( + uint128 userIndex, + uint128 ilkIndex, + uint128 amount, + uint128 warpTimeAmount, + uint256 functionIndex + ) + public + { + actorManager.fuzzedFallback(userIndex, ilkIndex, amount, warpTimeAmount, functionIndex); + } } diff --git a/test/unit/concrete/SwEthHandler.t.sol b/test/unit/concrete/SwEthHandler.t.sol deleted file mode 100644 index d9a0ef08..00000000 --- a/test/unit/concrete/SwEthHandler.t.sol +++ /dev/null @@ -1,105 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.21; - -import { SwEthHandler } from "../../../src/flash/lst/SwEthHandler.sol"; -import { Whitelist } from "../../../src/Whitelist.sol"; - -import { IonPoolSharedSetup } from "../../helpers/IonPoolSharedSetup.sol"; -import { ERC20PresetMinterPauser } from "../../helpers/ERC20PresetMinterPauser.sol"; - -import { IUniswapV3Pool } from "@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol"; - -contract MockUniswapPool { - address underlying; - - function token0() external pure returns (address) { - return address(0); - } - - function token1() external view returns (address) { - return underlying; - } - - function setUnderlying(address _underlying) external { - underlying = _underlying; - } - - function fee() external pure returns (uint24) { - return 500; - } -} - -contract SwEthHandler_Test is IonPoolSharedSetup { - SwEthHandler swEthHandler; - - uint8 ilkIndex = 2; - - function setUp() public override { - super.setUp(); - - MockUniswapPool mockPool = new MockUniswapPool(); - mockPool.setUnderlying(address(underlying)); - - // Ignore Uniswap args since they will be tested through forks - swEthHandler = new SwEthHandler( - ilkIndex, ionPool, gemJoins[ilkIndex], Whitelist(whitelist), IUniswapV3Pool(address(mockPool)) - ); - - // Remove debt ceiling for this test - for (uint8 i = 0; i < ionPool.ilkCount(); i++) { - ionPool.updateIlkDebtCeiling(i, type(uint256).max); - } - - ERC20PresetMinterPauser(_getUnderlying()).mint(lender1, INITIAL_LENDER_UNDERLYING_BALANCE); - - // uint256 riskAdjustedSpot = 0.9e18; - // spotOracles[1].setPrice(riskAdjustedSpot); - - vm.startPrank(lender1); - underlying.approve(address(ionPool), type(uint256).max); - ionPool.supply(lender1, 1e18, new bytes32[](0)); - vm.stopPrank(); - } - - function test_DepositAndBorrow() external { - uint256 depositAmount = 1e18; // in swEth - uint256 borrowAmount = 0.5e18; // in weth - - swEth.mint(address(this), depositAmount); - swEth.approve(address(swEthHandler), depositAmount); - ionPool.addOperator(address(swEthHandler)); - - assertEq(underlying.balanceOf(address(this)), 0); - assertEq(swEth.balanceOf(address(this)), depositAmount); - - swEthHandler.depositAndBorrow(depositAmount, borrowAmount, new bytes32[](0)); - - assertEq(underlying.balanceOf(address(this)), borrowAmount); - assertEq(swEth.balanceOf(address(this)), 0); - } - - function test_RepayAndWithdraw() external { - uint256 depositAmount = 1e18; // in swEth - uint256 borrowAmount = 0.5e18; // in weth - - swEth.mint(address(this), depositAmount); - swEth.approve(address(swEthHandler), depositAmount); - ionPool.addOperator(address(swEthHandler)); - - swEthHandler.depositAndBorrow(depositAmount, borrowAmount, new bytes32[](0)); - - underlying.approve(address(swEthHandler), borrowAmount); - - assertEq(underlying.balanceOf(address(this)), borrowAmount); - assertEq(swEth.balanceOf(address(this)), 0); - - swEthHandler.repayAndWithdraw(borrowAmount, depositAmount); - - assertEq(underlying.balanceOf(address(this)), 0); - assertEq(swEth.balanceOf(address(this)), depositAmount); - } - - function _getDebtCeiling(uint8) internal pure override returns (uint256) { - return type(uint256).max; - } -} diff --git a/test/unit/concrete/WstEthHandler.t.sol b/test/unit/concrete/WstEthHandler.t.sol deleted file mode 100644 index 079c63cb..00000000 --- a/test/unit/concrete/WstEthHandler.t.sol +++ /dev/null @@ -1,108 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.21; - -import { WstEthHandler } from "../../../src/flash/lst/WstEthHandler.sol"; -import { Whitelist } from "../../../src/Whitelist.sol"; - -import { IonPoolSharedSetup } from "../../helpers/IonPoolSharedSetup.sol"; -import { ERC20PresetMinterPauser } from "../../helpers/ERC20PresetMinterPauser.sol"; - -import { IUniswapV3Pool } from "@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol"; - -contract MockUniswapPool { - address underlying; - - function token0() external pure returns (address) { - return address(0); - } - - function token1() external view returns (address) { - return underlying; - } - - function setUnderlying(address _underlying) external { - underlying = _underlying; - } - - function fee() external pure returns (uint24) { - return 500; - } -} - -contract WstEthHandler_Test is IonPoolSharedSetup { - WstEthHandler wstEthHandler; - - uint8 ilkIndex = 0; - - address constant STETH = 0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84; - - function setUp() public override { - super.setUp(); - - MockUniswapPool mockPool = new MockUniswapPool(); - mockPool.setUnderlying(address(underlying)); - - // Ignore Uniswap args since they will be tested through forks - - // Deploy preset ERC20 code to STETH constant address to be compatible with constructor - vm.etch(STETH, address(wstEth).code); - - wstEthHandler = new WstEthHandler( - ilkIndex, ionPool, gemJoins[ilkIndex], Whitelist(whitelist), IUniswapV3Pool(address(mockPool)) - ); - - // Remove debt ceiling for this test - for (uint8 i = 0; i < ionPool.ilkCount(); i++) { - ionPool.updateIlkDebtCeiling(i, type(uint256).max); - } - - ERC20PresetMinterPauser(_getUnderlying()).mint(lender1, INITIAL_LENDER_UNDERLYING_BALANCE); - - vm.startPrank(lender1); - underlying.approve(address(ionPool), type(uint256).max); - ionPool.supply(lender1, 1e18, new bytes32[](0)); - vm.stopPrank(); - } - - function test_DepositAndBorrow() external { - uint256 depositAmount = 1e18; // in wstEth - uint256 borrowAmount = 0.5e18; // in weth - - wstEth.mint(address(this), depositAmount); - wstEth.approve(address(wstEthHandler), depositAmount); - ionPool.addOperator(address(wstEthHandler)); - - assertEq(underlying.balanceOf(address(this)), 0); - assertEq(wstEth.balanceOf(address(this)), depositAmount); - - wstEthHandler.depositAndBorrow(depositAmount, borrowAmount, new bytes32[](0)); - - assertEq(underlying.balanceOf(address(this)), borrowAmount); - assertEq(wstEth.balanceOf(address(this)), 0); - } - - function test_RepayAndWithdraw() external { - uint256 depositAmount = 1e18; // in wstEth - uint256 borrowAmount = 0.5e18; // in weth - - wstEth.mint(address(this), depositAmount); - wstEth.approve(address(wstEthHandler), depositAmount); - ionPool.addOperator(address(wstEthHandler)); - - wstEthHandler.depositAndBorrow(depositAmount, borrowAmount, new bytes32[](0)); - - underlying.approve(address(wstEthHandler), borrowAmount); - - assertEq(underlying.balanceOf(address(this)), borrowAmount); - assertEq(wstEth.balanceOf(address(this)), 0); - - wstEthHandler.repayAndWithdraw(borrowAmount, depositAmount); - - assertEq(underlying.balanceOf(address(this)), 0); - assertEq(wstEth.balanceOf(address(this)), depositAmount); - } - - function _getDebtCeiling(uint8) internal pure override returns (uint256) { - return type(uint256).max; - } -}