Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
0xmikko committed Mar 18, 2023
2 parents 5d7b32d + ac54a01 commit 58dcc7e
Show file tree
Hide file tree
Showing 26 changed files with 711 additions and 179 deletions.
2 changes: 1 addition & 1 deletion .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"recommendations": [
"esbenp.prettier-vscode",
"nomicfoundation.hardhat-solidity",
"JuanBlanco.solidity",
"dbaeumer.vscode-eslint"
]
}
13 changes: 3 additions & 10 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,16 @@
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[solidity]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
"editor.defaultFormatter": "JuanBlanco.solidity"
},

"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
"editor.tabSize": 2,
"eslint.validate": ["javascript", "typescript"],
"files.eol": "\n",
"solidity.formatter": "forge",
"solidity.packageDefaultDependenciesContractsDirectory": "contracts",
"solidity.packageDefaultDependenciesDirectory": "node_modules",
"solidity.remappings": [
"@chainlink/=node_modules/@chainlink/",
"@ensdomains/=node_modules/@ensdomains/",
"@openzeppelin/=node_modules/@openzeppelin/",
"ds-test/=lib/ds-test/src/",
"hardhat/=node_modules/hardhat/",
"@gearbox-protocol=node_modules/@gearbox-protocol/"
]
"solidity.compileUsingRemoteVersion": "v0.8.17",
"solidity.formatter": "forge"
}
89 changes: 51 additions & 38 deletions contracts/adapters/AbstractAdapter.sol
Original file line number Diff line number Diff line change
@@ -1,31 +1,39 @@
// SPDX-License-Identifier: GPL-2.0-or-later
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Holdings, 2022
// (c) Gearbox Holdings, 2023
pragma solidity ^0.8.17;

import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";

import {ACLNonReentrantTrait} from "../core/ACLNonReentrantTrait.sol";
import {IAdapter} from "../interfaces/adapters/IAdapter.sol";
import {IAddressProvider} from "@gearbox-protocol/core-v2/contracts/interfaces/IAddressProvider.sol";
import {ICreditManagerV2} from "../interfaces/ICreditManagerV2.sol";
import {IPool4626} from "../interfaces/IPool4626.sol";
import {ZeroAddressException} from "../interfaces/IErrors.sol";

/// @title Abstract adapter
/// @dev Inheriting adapters MUST use provided internal functions to perform all operations with credit accounts
abstract contract AbstractAdapter is IAdapter {
abstract contract AbstractAdapter is IAdapter, ACLNonReentrantTrait {
/// @notice Credit Manager the adapter is connected to
ICreditManagerV2 public immutable override creditManager;

/// @notice Address provider
IAddressProvider public immutable override addressProvider;

/// @notice Address of the contract the adapter is interacting with
address public immutable override targetContract;

/// @notice Constructor
/// @param _creditManager Credit Manager to connect this adapter to
/// @param _targetContract Address of the contract this adapter should interact with
constructor(address _creditManager, address _targetContract) {
if (_creditManager == address(0) || _targetContract == address(0)) {
revert ZeroAddressException();
} // F: [AA-2]
constructor(address _creditManager, address _targetContract)
ACLNonReentrantTrait(IPool4626(ICreditManagerV2(_creditManager).pool()).addressProvider())
{
if (_targetContract == address(0)) {
revert ZeroAddressException(); // F: [AA-2]
}

creditManager = ICreditManagerV2(_creditManager); // F: [AA-1]
addressProvider = IAddressProvider(IPool4626(creditManager.pool()).addressProvider()); // F: [AA-1]
targetContract = _targetContract; // F: [AA-1]
}

Expand All @@ -51,30 +59,35 @@ abstract contract AbstractAdapter is IAdapter {
return creditManager.getCreditAccountOrRevert(_creditFacade()); // F: [AA-4]
}

/// @dev Executes an arbitrary call from the Credit Account to the target contract
/// @param callData Data to call the target contract with
/// @return result Call output
function _execute(bytes memory callData) internal returns (bytes memory result) {
return creditManager.executeOrder(targetContract, callData); // F: [AA-6,9]
/// @dev Checks if token is registered as collateral token in the Credit Manager
/// @param token Token to check
/// @return tokenMask Collateral token mask
function _checkToken(address token) internal view returns (uint256 tokenMask) {
tokenMask = creditManager.tokenMasksMap(token); // F: [AA-6]
if (tokenMask == 0) {
revert TokenIsNotInAllowedList(token); // F: [AA-6]
}
}

/// @dev Approves the target contract to spend given token from the Credit Account
/// @param token Token to be approved
/// @param amount Amount to be approved
/// @dev Reverts if token is not registered as collateral token in the Credit Manager
function _approveToken(address token, uint256 amount) internal {
creditManager.approveCreditAccount(targetContract, token, amount); // F: [AA-6,10]
creditManager.approveCreditAccount(targetContract, token, amount); // F: [AA-7, AA-8]
}

/// @dev Enables a token in the Credit Account
/// @param token Address of the token to enable
/// @dev Reverts if token is not registered as collateral token in the Credit Manager
function _enableToken(address token) internal {
creditManager.checkAndEnableToken(token); // F: [AA-6,11]
creditManager.checkAndEnableToken(token); // F: [AA-7, AA-9]
}

/// @dev Disables a token in the Credit Account
/// @param token Address of the token to disable
function _disableToken(address token) internal {
creditManager.disableToken(token); // F: [AA-6,12]
creditManager.disableToken(token); // F: [AA-7, AA-10]
}

/// @dev Changes enabled tokens in the Credit Account
Expand All @@ -84,7 +97,14 @@ abstract contract AbstractAdapter is IAdapter {
/// determined in the adapter constructor, thus saving gas by avoiding querying them during execution
/// and combining multiple enable/disable operations into a single one
function _changeEnabledTokens(uint256 tokensToEnable, uint256 tokensToDisable) internal {
creditManager.changeEnabledTokens(tokensToEnable, tokensToDisable); // F: [AA-6,13]
creditManager.changeEnabledTokens(tokensToEnable, tokensToDisable); // F: [AA-7, AA-11]
}

/// @dev Executes an arbitrary call from the Credit Account to the target contract
/// @param callData Data to call the target contract with
/// @return result Call output
function _execute(bytes memory callData) internal returns (bytes memory result) {
return creditManager.executeOrder(targetContract, callData); // F: [AA-7, AA-12]
}

/// @dev Executes a swap operation on the target contract from the Credit Account
Expand All @@ -95,11 +115,13 @@ abstract contract AbstractAdapter is IAdapter {
/// @param disableTokenIn Whether the input token should be disabled afterwards
/// (for operations that spend the entire balance)
/// @return result Call output
/// @dev Reverts if tokenIn or tokenOut are not registered as collateral in the Credit Manager
function _executeSwapNoApprove(address tokenIn, address tokenOut, bytes memory callData, bool disableTokenIn)
internal
returns (bytes memory result)
{
return _executeSwap(tokenIn, tokenOut, callData, disableTokenIn, false); // F: [AA-6,7]
_checkToken(tokenIn); // F: [AA-15]
result = _executeSwap(tokenIn, tokenOut, callData, disableTokenIn); // F: [AA-7, AA-13]
}

/// @dev Executes a swap operation on the target contract from the Credit Account
Expand All @@ -110,36 +132,27 @@ abstract contract AbstractAdapter is IAdapter {
/// @param disableTokenIn Whether the input token should be disabled afterwards
/// (for operations that spend the entire balance)
/// @return result Call output
/// @dev Reverts if tokenIn or tokenOut are not registered as collateral in the Credit Manager
function _executeSwapSafeApprove(address tokenIn, address tokenOut, bytes memory callData, bool disableTokenIn)
internal
returns (bytes memory result)
{
return _executeSwap(tokenIn, tokenOut, callData, disableTokenIn, true); // F: [AA-6,8]
_approveToken(tokenIn, type(uint256).max); // F: [AA-14, AA-15]
result = _executeSwap(tokenIn, tokenOut, callData, disableTokenIn); // F: [AA-7, AA-14]
_approveToken(tokenIn, 1); // F: [AA-14]
}

/// @dev Implementation of `_executeSwap...` operations
/// @dev Kept private as only the internal wrappers are intended to be used
/// by inheritors
function _executeSwap(
address tokenIn,
address tokenOut,
bytes memory callData,
bool disableTokenIn,
bool allowTokenIn
) private returns (bytes memory result) {
if (allowTokenIn) {
_approveToken(tokenIn, type(uint256).max); // F: [AA-8]
}

result = _execute(callData); // F: [AA-7,8]

if (allowTokenIn) {
_approveToken(tokenIn, 1); // F: [AA-8]
}

function _executeSwap(address tokenIn, address tokenOut, bytes memory callData, bool disableTokenIn)
private
returns (bytes memory result)
{
result = _execute(callData); // F: [AA-13, AA-14]
if (disableTokenIn) {
_disableToken(tokenIn); // F: [AA-7,8]
_disableToken(tokenIn); // F: [AA-13, AA-14]
}
_enableToken(tokenOut); // F: [AA-7,8]
_enableToken(tokenOut); // F: [AA-13, AA-14, AA-15]
}
}
Loading

0 comments on commit 58dcc7e

Please sign in to comment.