Skip to content

Conversation

@bhargavbh
Copy link

Added a symbolic IRM contract which returns a non-deterministic rate for the borrowRate() and borrowRateView() functions. The Morpho contract now calls a symbolic IRM instead of Mock IRM. Halmos tests pass with slightly higher path exploration.

@bhargavbh
Copy link
Author

bhargavbh commented Nov 28, 2025

the linter fails because i cast a Uint256 into Uint128. Halmos only has the symbolic version for Uint256 but not Uint128. Hence i cast it to Uint128. For a halmos test, this is perfectly reasonable and sound since i am casting down and all the symbolic values of Uint128 are covered. Is there a better way around? @QGarchery


// A symbolic IRM for Halmos Tests.
contract IrmSymbolic is IIrm, SymTest, Test {
using MathLib for uint128;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
using MathLib for uint128;

Comment on lines +4 to +19
import "../../lib/forge-std/src/Test.sol";
import {SymTest} from "../../lib/halmos-cheatcodes/src/SymTest.sol";

import {IMorpho} from "../../src/interfaces/IMorpho.sol";
import {IrmMock} from "../../src/mocks/IrmMock.sol";
import {ERC20Mock} from "../../src/mocks/ERC20Mock.sol";
import {OracleMock} from "../../src/mocks/OracleMock.sol";
import {FlashBorrowerMock} from "../../src/mocks/FlashBorrowerMock.sol";

import "../../src/Morpho.sol";
import "../../src/libraries/ConstantsLib.sol";
import {MorphoLib} from "../../src/libraries/periphery/MorphoLib.sol";

import {IIrm} from "../../src/interfaces/IIrm.sol";

import {MathLib} from "../../src/libraries/MathLib.sol";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

optional

Suggested change
import {MathLib} from "../../src/libraries/MathLib.sol";
import "../../lib/forge-std/src/Test.sol";
import {SymTest} from "../../lib/halmos-cheatcodes/src/SymTest.sol";
import {IMorpho} from "../../src/interfaces/IMorpho.sol";
import {IrmMock} from "../../src/mocks/IrmMock.sol";
import {IIrm} from "../../src/interfaces/IIrm.sol";
import {ERC20Mock} from "../../src/mocks/ERC20Mock.sol";
import {OracleMock} from "../../src/mocks/OracleMock.sol";
import {FlashBorrowerMock} from "../../src/mocks/FlashBorrowerMock.sol";
import "../../src/Morpho.sol";
import "../../src/libraries/ConstantsLib.sol";
import {MorphoLib} from "../../src/libraries/periphery/MorphoLib.sol";
import {MathLib} from "../../src/libraries/MathLib.sol";

@bhargavbh
Copy link
Author

bhargavbh commented Dec 12, 2025

interestingly, all tests pass with symbolic initialised market except check_borrowLessThanSupply() which is the only property reasoning about totalSupplyAssets and totalBorrowAssets. Verifying it generates 46 constraints but yices timesout on solving the last constraint. Attempting to run with other solvers.


assert(
morpho.totalSupplyAssets(id) != 0 && morpho.totalSupplyShares(id) != 0 && morpho.totalBorrowAssets(id) != 0
&& morpho.totalBorrowShares(id) != 0 && morpho.fee(id) != 0
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

interesting this test passes as we assert fee!=0. However, fee is set symbolic uint256, and hence can very well be zero.

vm.assume(morpho.totalBorrowAssets(id) <= morpho.totalSupplyAssets(id));

// all solvers timeout on liquidate
vm.assume(selector != morpho.liquidate.selector);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we either remove the whole test or keep it excluding liquidate.

@bhargavbh bhargavbh requested a review from MathisGD December 30, 2025 13:32
@bhargavbh
Copy link
Author

removed the check_borrowLessThanSupply test since the solver timesout. The other tests are meaningful now with the symbolicIRM and the initial state is symbolic (non-zero).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants