Skip to content

Commit

Permalink
fix: handle demote 2 token to isolate at once
Browse files Browse the repository at this point in the history
  • Loading branch information
69alpacas committed Jul 21, 2023
1 parent 3a78cd0 commit f816455
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 6 deletions.
15 changes: 9 additions & 6 deletions solidity/contracts/money-market/facets/BorrowFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,7 @@ contract BorrowFacet is IBorrowFacet {
/// @param _subAccountId An index to derive the subaccount
/// @param _token The token to borrow
/// @param _amount The amount to borrow
function borrow(
address _account,
uint256 _subAccountId,
address _token,
uint256 _amount
) external nonReentrant {
function borrow(address _account, uint256 _subAccountId, address _token, uint256 _amount) external nonReentrant {
LibMoneyMarket01.MoneyMarketDiamondStorage storage moneyMarketDs = LibMoneyMarket01.moneyMarketDiamondStorage();

LibMoneyMarket01.onlyLive(moneyMarketDs);
Expand Down Expand Up @@ -335,6 +330,14 @@ contract BorrowFacet is IBorrowFacet {
) {
revert BorrowFacet_InvalidAssetTier();
}
// Edge case: when demote multiple market to ISOLATE at once
// there could be ISOLATE token along with something else in subaccount, forbid user from borrowing anything
if (
moneyMarketDs.subAccountDebtShares[_subAccount].has(_token) &&
moneyMarketDs.subAccountDebtShares[_subAccount].size > 1
) {
revert BorrowFacet_InvalidAssetTier();
}
// Revert if trying to borrow other tier while borrowing ISOLATE token
} else if (_hasIsolateAsset) {
revert BorrowFacet_InvalidAssetTier();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { MoneyMarket_BaseTest, MockERC20, console } from "../MoneyMarket_BaseTes
// libraries
import { LibMoneyMarket01 } from "../../../contracts/money-market/libraries/LibMoneyMarket01.sol";
import { LibDoublyLinkedList } from "../../../contracts/money-market/libraries/LibDoublyLinkedList.sol";
import { LibConstant } from "../../../contracts/money-market/libraries/LibConstant.sol";
// interfaces
import { IBorrowFacet } from "../../../contracts/money-market/interfaces/IBorrowFacet.sol";
import { IAdminFacet } from "../../../contracts/money-market/interfaces/IAdminFacet.sol";
Expand Down Expand Up @@ -414,4 +415,61 @@ contract MoneyMarket_OverCollatBorrow_BorrowTest is MoneyMarket_BaseTest {
_poolId = viewFacet.getMiniFLPoolIdOfToken(_debtToken);
assertEq(_miniFL.getUserTotalAmountOf(_poolId, BOB), _borrowAmount);
}

function testRevert_WhenDemoteMarket_UserHasMoreThanOneIsolate_ShouldNotBeAbleToBorrow() public {
// prepare
usdc.mint(ALICE, 1e10);
vm.prank(ALICE);
accountManager.deposit(address(usdc), 1e10);

btc.mint(BOB, 1 ether);
mockOracle.setTokenPrice(address(btc), 30000 ether);

// BOB borrow weth and usdc
vm.startPrank(BOB);
btc.approve(address(accountManager), type(uint256).max);
accountManager.addCollateralFor(BOB, subAccount0, address(btc), 1 ether);
accountManager.borrow(subAccount0, address(weth), 1 ether);
accountManager.borrow(subAccount0, address(usdc), 1e8);
vm.stopPrank();

// Demote both token to ISOLATE tier
IAdminFacet.TokenConfigInput[] memory tokenConfigs = new IAdminFacet.TokenConfigInput[](2);
tokenConfigs[0] = IAdminFacet.TokenConfigInput({
tier: LibConstant.AssetTier.ISOLATE,
collateralFactor: 9000,
borrowingFactor: 9000,
maxBorrow: 30 ether,
maxCollateral: 100 ether
});
tokenConfigs[1] = IAdminFacet.TokenConfigInput({
tier: LibConstant.AssetTier.ISOLATE,
collateralFactor: 9000,
borrowingFactor: 9000,
maxBorrow: normalizeEther(100 ether, 6),
maxCollateral: normalizeEther(100 ether, 6)
});
address[] memory tokens = new address[](2);
tokens[0] = address(weth);
tokens[1] = address(usdc);
adminFacet.setTokenConfigs(tokens, tokenConfigs);

// Should not be able to borrow anything after both got demoted
vm.startPrank(BOB);
vm.expectRevert(abi.encodeWithSelector(IBorrowFacet.BorrowFacet_InvalidAssetTier.selector));
accountManager.borrow(subAccount0, address(usdc), 1e8);
vm.expectRevert(abi.encodeWithSelector(IBorrowFacet.BorrowFacet_InvalidAssetTier.selector));
accountManager.borrow(subAccount0, address(btc), 0.01 ether);
// Should be able to repay
accountManager.repayFor(BOB, subAccount0, address(usdc), 1e8, 1e8);

// After repay one ISOLATE debt
// should be able to borrow more of the remaining token
accountManager.borrow(subAccount0, address(weth), 0.01 ether);
// should not be able to borrow any other token
vm.expectRevert(abi.encodeWithSelector(IBorrowFacet.BorrowFacet_InvalidAssetTier.selector));
accountManager.borrow(subAccount0, address(usdc), 1e8);
vm.expectRevert(abi.encodeWithSelector(IBorrowFacet.BorrowFacet_InvalidAssetTier.selector));
accountManager.borrow(subAccount0, address(btc), 0.01 ether);
}
}

0 comments on commit f816455

Please sign in to comment.