Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: add lltv shifting and authorization double spend tests #449

Merged
merged 4 commits into from
Aug 30, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion test/forge/BaseTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ contract BaseTest is Test {
uint256 internal constant MAX_TEST_AMOUNT = 1e28;
uint256 internal constant MIN_TEST_SHARES = MIN_TEST_AMOUNT * SharesMathLib.VIRTUAL_SHARES;
uint256 internal constant MAX_TEST_SHARES = MAX_TEST_AMOUNT * SharesMathLib.VIRTUAL_SHARES;
uint256 internal constant MIN_TEST_LLTV = 0.01 ether;
uint256 internal constant MAX_TEST_LLTV = 0.99 ether;
uint256 internal constant MIN_COLLATERAL_PRICE = 1e10;
uint256 internal constant MAX_COLLATERAL_PRICE = 1e40;
uint256 internal constant MAX_COLLATERAL_ASSETS = type(uint128).max;
Expand All @@ -36,7 +38,7 @@ contract BaseTest is Test {
address internal LIQUIDATOR = _addrFromHashedString("Morpho Liquidator");
address internal OWNER = _addrFromHashedString("Morpho Owner");

uint256 internal constant LLTV = 0.8 ether;
uint256 internal LLTV = 0.8 ether;
Rubilmax marked this conversation as resolved.
Show resolved Hide resolved

Morpho internal morpho;
ERC20 internal borrowableToken;
Expand Down Expand Up @@ -112,6 +114,21 @@ contract BaseTest is Test {
vm.warp(block.timestamp + 1 days);
}

function _setLltv(uint256 lltv) internal {
Rubilmax marked this conversation as resolved.
Show resolved Hide resolved
LLTV = lltv;
marketParams =
MarketParams(address(borrowableToken), address(collateralToken), address(oracle), address(irm), lltv);
id = marketParams.id();

vm.startPrank(OWNER);
if (!morpho.isLltvEnabled(lltv)) morpho.enableLltv(lltv);
if (morpho.lastUpdate(marketParams.id()) == 0) morpho.createMarket(marketParams);
vm.stopPrank();

vm.roll(block.number + 1);
vm.warp(block.timestamp + 1 days);
}

function _addrFromHashedString(string memory str) internal pure returns (address) {
return address(uint160(uint256(keccak256(bytes(str)))));
}
Expand Down Expand Up @@ -170,6 +187,10 @@ contract BaseTest is Test {
return (amountCollateral, amountBorrowed, priceCollateral);
}

function _boundTestLltv(uint256 lltv) internal view returns (uint256) {
Rubilmax marked this conversation as resolved.
Show resolved Hide resolved
return bound(lltv, MIN_TEST_LLTV, MAX_TEST_LLTV);
}

function _boundValidLltv(uint256 lltv) internal view returns (uint256) {
return bound(lltv, 0, WAD - 1);
}
Expand Down
18 changes: 18 additions & 0 deletions test/forge/integration/AuthorizationIntegrationTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -88,4 +88,22 @@ contract AuthorizationIntegrationTest is BaseTest {
assertEq(morpho.isAuthorized(authorization.authorizer, authorization.authorized), authorization.isAuthorized);
assertEq(morpho.nonce(authorization.authorizer), 1);
}

function testAuthorizationFailsWithReusedSig(Authorization memory authorization, uint256 privateKey) public {
authorization.deadline = bound(authorization.deadline, block.timestamp + 1, type(uint256).max);

// Private key must be less than the secp256k1 curve order.
privateKey = bound(privateKey, 1, type(uint32).max);
authorization.nonce = 0;
authorization.authorizer = vm.addr(privateKey);

Signature memory sig;
bytes32 digest = SigUtils.getTypedDataHash(morpho.DOMAIN_SEPARATOR(), authorization);
(sig.v, sig.r, sig.s) = vm.sign(privateKey, digest);

morpho.setAuthorizationWithSig(authorization, sig);

vm.expectRevert(bytes(ErrorsLib.INVALID_NONCE));
morpho.setAuthorizationWithSig(authorization, sig);
}
}
31 changes: 23 additions & 8 deletions test/forge/integration/LiquidateIntegrationTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,16 @@ contract LiquidateIntegrationTest is BaseTest {
using MorphoLib for Morpho;
using SharesMathLib for uint256;

function testLiquidateNotCreatedMarket(MarketParams memory marketParamsFuzz) public {
function testLiquidateNotCreatedMarket(MarketParams memory marketParamsFuzz, uint256 lltv) public {
_setLltv(_boundTestLltv(lltv));
vm.assume(neq(marketParamsFuzz, marketParams));

vm.expectRevert(bytes(ErrorsLib.MARKET_NOT_CREATED));
morpho.liquidate(marketParamsFuzz, address(this), 1, 0, hex"");
}

function testLiquidateZeroAmount() public {
function testLiquidateZeroAmount(uint256 lltv) public {
_setLltv(_boundTestLltv(lltv));
vm.prank(BORROWER);

vm.expectRevert(bytes(ErrorsLib.INCONSISTENT_INPUT));
Expand All @@ -37,12 +39,14 @@ contract LiquidateIntegrationTest is BaseTest {
uint256 amountSupplied,
uint256 amountBorrowed,
uint256 amountSeized,
uint256 priceCollateral
uint256 priceCollateral,
uint256 lltv
) public {
_setLltv(_boundTestLltv(lltv));
(amountCollateral, amountBorrowed, priceCollateral) =
_boundHealthyPosition(amountCollateral, amountBorrowed, priceCollateral);

amountSupplied = bound(amountSupplied, amountBorrowed, MAX_TEST_AMOUNT);
amountSupplied = bound(amountSupplied, amountBorrowed, amountBorrowed + MAX_TEST_AMOUNT);
_supply(amountSupplied);

amountSeized = bound(amountSeized, 1, amountCollateral);
Expand All @@ -67,18 +71,25 @@ contract LiquidateIntegrationTest is BaseTest {
uint256 amountSupplied,
uint256 amountBorrowed,
uint256 amountSeized,
uint256 priceCollateral
uint256 priceCollateral,
uint256 lltv
) public {
_setLltv(_boundTestLltv(lltv));
(amountCollateral, amountBorrowed, priceCollateral) =
_boundUnhealthyPosition(amountCollateral, amountBorrowed, priceCollateral);

console2.log(amountCollateral);
console2.log(amountBorrowed);
console2.log(priceCollateral);
Rubilmax marked this conversation as resolved.
Show resolved Hide resolved

vm.assume(amountCollateral > 1);

amountSupplied = bound(amountSupplied, amountBorrowed, MAX_TEST_AMOUNT);
amountSupplied = bound(amountSupplied, amountBorrowed, amountBorrowed + MAX_TEST_AMOUNT);
_supply(amountSupplied);

uint256 incentive = _liquidationIncentive(marketParams.lltv);
uint256 maxSeized = amountBorrowed.wMulDown(incentive).mulDivDown(ORACLE_PRICE_SCALE, priceCollateral);
vm.assume(maxSeized != 0);
amountSeized = bound(amountSeized, 1, min(maxSeized, amountCollateral - 1));
uint256 expectedRepaid = amountSeized.mulDivUp(priceCollateral, ORACLE_PRICE_SCALE).wDivUp(incentive);

Expand Down Expand Up @@ -129,8 +140,10 @@ contract LiquidateIntegrationTest is BaseTest {
uint256 amountSupplied,
uint256 amountBorrowed,
uint256 sharesRepaid,
uint256 priceCollateral
uint256 priceCollateral,
uint256 lltv
) public {
_setLltv(_boundTestLltv(lltv));
(amountCollateral, amountBorrowed, priceCollateral) =
_boundUnhealthyPosition(amountCollateral, amountBorrowed, priceCollateral);

Expand Down Expand Up @@ -204,8 +217,10 @@ contract LiquidateIntegrationTest is BaseTest {
uint256 amountCollateral,
uint256 amountSupplied,
uint256 amountBorrowed,
uint256 priceCollateral
uint256 priceCollateral,
uint256 lltv
) public {
_setLltv(_boundTestLltv(lltv));
LiquidateBadDebtTestParams memory params;

(amountCollateral, amountBorrowed, priceCollateral) =
Expand Down