Skip to content

Commit

Permalink
fix: lts reading for quoted tokens optimisation
Browse files Browse the repository at this point in the history
  • Loading branch information
0xmikko committed May 9, 2023
1 parent 994197b commit 759215b
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 37 deletions.
2 changes: 1 addition & 1 deletion contracts/credit/CreditFacadeV3.sol
Original file line number Diff line number Diff line change
Expand Up @@ -710,7 +710,7 @@ contract CreditFacadeV3 is ICreditFacade, ACLNonReentrantTrait {
}

function _setExternalCallCreditAccount(address creditAccount) internal {
creditManager.setCaForExternalCall(creditAccount); // F:[FA-26]
creditManager.setCreditAccountForExternalCall(creditAccount); // F:[FA-26]
}

function _revertIfNoPermission(uint256 flags, uint256 permission) internal pure {
Expand Down
37 changes: 19 additions & 18 deletions contracts/credit/CreditManagerV3.sol
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,8 @@ contract CreditManagerV3 is ICreditManagerV3, SanityCheckTrait, ReentrancyGuard
if (supportsQuotas) {
cumulativeQuotaInterest = creditAccountInfo[creditAccount].cumulativeQuotaInterest - 1;
{
(address[] memory tokens,) = _getQuotedTokens(enabledTokensMask);
(address[] memory tokens,) =
_getQuotedTokens({enabledTokensMask: enabledTokensMask, withLTs: false});
if (tokens.length > 0) {
cumulativeQuotaInterest += poolQuotaKeeper().accrueQuotaInterest(creditAccount, tokens); // F: [CMQ-4,5]
}
Expand Down Expand Up @@ -614,7 +615,7 @@ contract CreditManagerV3 is ICreditManagerV3, SanityCheckTrait, ReentrancyGuard
uint256 quotaInterest;

if (supportsQuotas) {
(address[] memory tokens,) = _getQuotedTokens(enabledTokensMask);
(address[] memory tokens,) = _getQuotedTokens({enabledTokensMask: enabledTokensMask, withLTs: false});

quotaInterest = creditAccountInfo[creditAccount].cumulativeQuotaInterest - 1;

Expand Down Expand Up @@ -716,7 +717,7 @@ contract CreditManagerV3 is ICreditManagerV3, SanityCheckTrait, ReentrancyGuard
returns (uint256 totalValueUSD, uint256 twvUSD, uint256 quotaInterest, address[] memory tokens)
{
uint256[] memory lts;
(tokens, lts) = _getQuotedTokens(enabledTokensMask);
(tokens, lts) = _getQuotedTokens({enabledTokensMask: enabledTokensMask, withLTs: true});

if (tokens.length > 0) {
/// If credit account has any connected token - then check that
Expand Down Expand Up @@ -798,12 +799,16 @@ contract CreditManagerV3 is ICreditManagerV3, SanityCheckTrait, ReentrancyGuard
}
}

//
// QUOTAS MANAGEMENT
//

/// @dev Returns the array of quoted tokens that are enabled on the account
function getQuotedTokens(address creditAccount) public view returns (address[] memory tokens) {
(tokens,) = _getQuotedTokens(enabledTokensMaskOf(creditAccount));
(tokens,) = _getQuotedTokens({enabledTokensMask: enabledTokensMaskOf(creditAccount), withLTs: false});
}

function _getQuotedTokens(uint256 enabledTokensMask)
function _getQuotedTokens(uint256 enabledTokensMask, bool withLTs)
internal
view
returns (address[] memory tokens, uint256[] memory lts)
Expand All @@ -819,18 +824,14 @@ contract CreditManagerV3 is ICreditManagerV3, SanityCheckTrait, ReentrancyGuard
unchecked {
for (uint256 tokenMask = 2; tokenMask <= quotedMask; tokenMask <<= 1) {
if (quotedMask & tokenMask != 0) {
(tokens[j], lts[j]) = collateralTokensByMask(tokenMask);
(tokens[j], lts[j]) = _collateralTokensByMask({tokenMask: tokenMask, calcLT: withLTs});
++j;
}
}
}
}
}

//
// QUOTAS MANAGEMENT
//

/// @dev Updates credit account's quotas for multiple tokens
/// @param creditAccount Address of credit account
function updateQuota(address creditAccount, address token, int96 quotaChange)
Expand Down Expand Up @@ -930,6 +931,13 @@ contract CreditManagerV3 is ICreditManagerV3, SanityCheckTrait, ReentrancyGuard
delivered = IERC20(token)._balanceOf(to) - balanceBefore;
}

function _checkEnabledTokenLength(uint256 enabledTokensMask) internal view {
uint256 totalTokensEnabled = enabledTokensMask.calcEnabledTokens();
if (totalTokensEnabled > maxAllowedEnabledTokenLength) {
revert TooManyEnabledTokensException();
}
}

//
// GETTERS
//
Expand Down Expand Up @@ -1257,13 +1265,6 @@ contract CreditManagerV3 is ICreditManagerV3, SanityCheckTrait, ReentrancyGuard
emit SetCreditConfigurator(_creditConfigurator); // F:[CM-58]
}

function _checkEnabledTokenLength(uint256 enabledTokensMask) internal view {
uint256 totalTokensEnabled = enabledTokensMask.calcEnabledTokens();
if (totalTokensEnabled > maxAllowedEnabledTokenLength) {
revert TooManyEnabledTokensException();
}
}

/// ----------- ///
/// WITHDRAWALS ///
/// ----------- ///
Expand Down Expand Up @@ -1351,7 +1352,7 @@ contract CreditManagerV3 is ICreditManagerV3, SanityCheckTrait, ReentrancyGuard
}

///
function setCaForExternalCall(address creditAccount) external override creditFacadeOnly {
function setCreditAccountForExternalCall(address creditAccount) external override creditFacadeOnly {
_externalCallCreditAccount = creditAccount;
}

Expand Down
2 changes: 1 addition & 1 deletion contracts/interfaces/ICreditManagerV3.sol
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ interface ICreditManagerV3 is ICreditManagerV3Events, IVersion {
/// @param revocations Spender/token pairs to revoke allowances for
function revokeAdapterAllowances(address creditAccount, RevocationPair[] calldata revocations) external;

function setCaForExternalCall(address creditAccount) external;
function setCreditAccountForExternalCall(address creditAccount) external;

function externalCallCreditAccountOrRevert() external view returns (address creditAccount);

Expand Down
2 changes: 1 addition & 1 deletion contracts/test/unit/adapters/AbstractAdapter.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,6 @@ contract AbstractAdapterTest is DSTest, BalanceHelper, CreditFacadeTestHelper {
function _openExternalCallCreditAccount() internal returns (address creditAccount) {
(creditAccount,) = _openTestCreditAccount();
evm.prank(address(creditFacade));
creditManager.setCaForExternalCall(creditAccount);
creditManager.setCreditAccountForExternalCall(creditAccount);
}
}
36 changes: 26 additions & 10 deletions contracts/test/unit/credit/CreditFacade.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -695,7 +695,9 @@ contract CreditFacadeTest is
MultiCall({target: address(adapterMock), callData: abi.encodeCall(AdapterMock.dumbCall, (0, 0))})
);

evm.expectCall(address(creditManager), abi.encodeCall(ICreditManagerV3.setCaForExternalCall, (creditAccount)));
evm.expectCall(
address(creditManager), abi.encodeCall(ICreditManagerV3.setCreditAccountForExternalCall, (creditAccount))
);

evm.expectEmit(true, false, false, false);
emit StartMultiCall(creditAccount);
Expand All @@ -712,7 +714,9 @@ contract CreditFacadeTest is
evm.expectEmit(false, false, false, true);
emit FinishMultiCall();

evm.expectCall(address(creditManager), abi.encodeCall(ICreditManagerV3.setCaForExternalCall, (address(1))));
evm.expectCall(
address(creditManager), abi.encodeCall(ICreditManagerV3.setCreditAccountForExternalCall, (address(1)))
);

// evm.expectCall(
// address(creditManager),
Expand Down Expand Up @@ -781,7 +785,9 @@ contract CreditFacadeTest is

// EXPECTED STACK TRACE & EVENTS

evm.expectCall(address(creditManager), abi.encodeCall(ICreditManagerV3.setCaForExternalCall, (creditAccount)));
evm.expectCall(
address(creditManager), abi.encodeCall(ICreditManagerV3.setCreditAccountForExternalCall, (creditAccount))
);

evm.expectEmit(true, false, false, false);
emit StartMultiCall(creditAccount);
Expand All @@ -798,7 +804,9 @@ contract CreditFacadeTest is
evm.expectEmit(false, false, false, false);
emit FinishMultiCall();

evm.expectCall(address(creditManager), abi.encodeCall(ICreditManagerV3.setCaForExternalCall, (address(1))));
evm.expectCall(
address(creditManager), abi.encodeCall(ICreditManagerV3.setCreditAccountForExternalCall, (address(1)))
);

// Total value = 2 * DAI_ACCOUNT_AMOUNT, cause we have x2 leverage
uint256 totalValue = 2 * DAI_ACCOUNT_AMOUNT;
Expand Down Expand Up @@ -1368,7 +1376,9 @@ contract CreditFacadeTest is
MultiCall({target: address(adapterMock), callData: abi.encodeCall(AdapterMock.dumbCall, (0, 0))})
);

evm.expectCall(address(creditManager), abi.encodeCall(ICreditManagerV3.setCaForExternalCall, (creditAccount)));
evm.expectCall(
address(creditManager), abi.encodeCall(ICreditManagerV3.setCreditAccountForExternalCall, (creditAccount))
);

evm.expectEmit(true, true, false, true);
emit StartMultiCall(creditAccount);
Expand All @@ -1385,7 +1395,9 @@ contract CreditFacadeTest is
evm.expectEmit(false, false, false, true);
emit FinishMultiCall();

evm.expectCall(address(creditManager), abi.encodeCall(ICreditManagerV3.setCaForExternalCall, (address(1))));
evm.expectCall(
address(creditManager), abi.encodeCall(ICreditManagerV3.setCreditAccountForExternalCall, (address(1)))
);

evm.expectCall(
address(creditManager),
Expand Down Expand Up @@ -1871,7 +1883,7 @@ contract CreditFacadeTest is

// // EXPECTED STACK TRACE & EVENTS

// evm.expectCall(address(creditManager), abi.encodeCall(ICreditManagerV3.setCaForExternalCall, (creditAccount)));
// evm.expectCall(address(creditManager), abi.encodeCall(ICreditManagerV3.setCreditAccountForExternalCall, (creditAccount)));

// evm.expectEmit(true, false, false, false);
// emit StartMultiCall(creditAccount);
Expand All @@ -1888,7 +1900,7 @@ contract CreditFacadeTest is
// evm.expectEmit(false, false, false, false);
// emit FinishMultiCall();

// evm.expectCall(address(creditManager), abi.encodeCall(ICreditManagerV3.setCaForExternalCall, (address(1))));
// evm.expectCall(address(creditManager), abi.encodeCall(ICreditManagerV3.setCreditAccountForExternalCall, (address(1))));
// // Total value = 2 * DAI_ACCOUNT_AMOUNT, cause we have x2 leverage
// uint256 totalValue = balance;

Expand Down Expand Up @@ -2076,7 +2088,9 @@ contract CreditFacadeTest is
MultiCall({target: address(adapterMock), callData: abi.encodeCall(AdapterMock.dumbCall, (0, 0))})
);

evm.expectCall(address(creditManager), abi.encodeCall(ICreditManagerV3.setCaForExternalCall, (creditAccount)));
evm.expectCall(
address(creditManager), abi.encodeCall(ICreditManagerV3.setCreditAccountForExternalCall, (creditAccount))
);

evm.expectEmit(true, true, false, true);
emit StartMultiCall(creditAccount);
Expand All @@ -2093,7 +2107,9 @@ contract CreditFacadeTest is
evm.expectEmit(false, false, false, true);
emit FinishMultiCall();

evm.expectCall(address(creditManager), abi.encodeCall(ICreditManagerV3.setCaForExternalCall, (address(1))));
evm.expectCall(
address(creditManager), abi.encodeCall(ICreditManagerV3.setCreditAccountForExternalCall, (address(1)))
);

evm.expectCall(
address(creditManager),
Expand Down
10 changes: 5 additions & 5 deletions contracts/test/unit/credit/CreditManager.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -1214,7 +1214,7 @@ contract CreditManagerTest is DSTest, ICreditManagerV3Events, BalanceHelper {
/// @dev [CM-25A]: approveCreditAccount reverts if the token is not added
function test_CM_25A_approveCreditAccount_reverts_if_the_token_is_not_added() public {
(,,, address creditAccount) = _openCreditAccount();
creditManager.setCaForExternalCall(creditAccount);
creditManager.setCreditAccountForExternalCall(creditAccount);

evm.prank(CONFIGURATOR);
creditManager.setContractAllowance(ADAPTER, DUMB_ADDRESS);
Expand All @@ -1228,7 +1228,7 @@ contract CreditManagerTest is DSTest, ICreditManagerV3Events, BalanceHelper {
/// @dev [CM-26]: approveCreditAccount approves with desired allowance
function test_CM_26_approveCreditAccount_approves_with_desired_allowance() public {
(,,, address creditAccount) = _openCreditAccount();
creditManager.setCaForExternalCall(creditAccount);
creditManager.setCreditAccountForExternalCall(creditAccount);

evm.prank(CONFIGURATOR);
creditManager.setContractAllowance(ADAPTER, DUMB_ADDRESS);
Expand All @@ -1247,7 +1247,7 @@ contract CreditManagerTest is DSTest, ICreditManagerV3Events, BalanceHelper {
/// @dev [CM-27A]: approveCreditAccount works for ERC20 that revert if allowance > 0 before approve
function test_CM_27A_approveCreditAccount_works_for_ERC20_with_approve_restrictions() public {
(,,, address creditAccount) = _openCreditAccount();
creditManager.setCaForExternalCall(creditAccount);
creditManager.setCreditAccountForExternalCall(creditAccount);

evm.prank(CONFIGURATOR);
creditManager.setContractAllowance(ADAPTER, DUMB_ADDRESS);
Expand All @@ -1269,7 +1269,7 @@ contract CreditManagerTest is DSTest, ICreditManagerV3Events, BalanceHelper {
// /// @dev [CM-27B]: approveCreditAccount works for ERC20 that returns false if allowance > 0 before approve
function test_CM_27B_approveCreditAccount_works_for_ERC20_with_approve_restrictions() public {
(,,, address creditAccount) = _openCreditAccount();
creditManager.setCaForExternalCall(creditAccount);
creditManager.setCreditAccountForExternalCall(creditAccount);

address approveFalseToken = address(new ERC20ApproveRestrictedFalse());

Expand All @@ -1295,7 +1295,7 @@ contract CreditManagerTest is DSTest, ICreditManagerV3Events, BalanceHelper {
/// @dev [CM-29]: executeOrder calls credit account method and emit event
function test_CM_29_executeOrder_calls_credit_account_method_and_emit_event() public {
(,,, address creditAccount) = _openCreditAccount();
creditManager.setCaForExternalCall(creditAccount);
creditManager.setCreditAccountForExternalCall(creditAccount);

TargetContractMock targetMock = new TargetContractMock();

Expand Down
2 changes: 1 addition & 1 deletion contracts/test/unit/pool/LinearInterestRateModel.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ contract LinearInterestRateModelTest is DSTest {
expectedLiquidity: 100,
availableLiquidity: 60,
/// EXPECTED VALUES
// 15% + 5% (r1) * 40% (utilisation) / 80% (u1)
// 15% (rBase) + 5% (r1) * 40% (utilisation) / 80% (u1)
expectedBorrowRate: (15_00 + 5_00 * 40 / 80) * RAY / PERCENTAGE_FACTOR,
expectedAvailableToBorrow: 55,
expectedRevert: false
Expand Down

0 comments on commit 759215b

Please sign in to comment.