Skip to content

Commit

Permalink
feat: _executeSwapNoApprove reverts on bad tokens
Browse files Browse the repository at this point in the history
  • Loading branch information
lekhovitsky committed Mar 18, 2023
1 parent 3ae9f36 commit 6988e65
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 3 deletions.
11 changes: 8 additions & 3 deletions contracts/adapters/AbstractAdapter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,14 @@ abstract contract AbstractAdapter is IAdapter, ACLNonReentrantTrait {
/// @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-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-7, AA-9]
}
Expand Down Expand Up @@ -113,11 +115,13 @@ abstract contract AbstractAdapter is IAdapter, ACLNonReentrantTrait {
/// @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); // F: [AA-7, AA-13]
_checkToken(tokenIn); // F: [AA-13, 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 @@ -128,11 +132,12 @@ abstract contract AbstractAdapter is IAdapter, ACLNonReentrantTrait {
/// @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)
{
_approveToken(tokenIn, type(uint256).max); // F: [AA-14]
_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]
}
Expand All @@ -148,6 +153,6 @@ abstract contract AbstractAdapter is IAdapter, ACLNonReentrantTrait {
if (disableTokenIn) {
_disableToken(tokenIn); // F: [AA-13, AA-14]
}
_enableToken(tokenOut); // F: [AA-13, AA-14]
_enableToken(tokenOut); // F: [AA-13, AA-14, AA-15]
}
}
36 changes: 36 additions & 0 deletions contracts/test/adapters/AbstractAdapter.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -378,4 +378,40 @@ contract AbstractAdapterTest is
assertEq(IERC20(usdc).allowance(ca, address(targetMock)), 1, "Incorrect allowance set");
}
}

/// @dev [AA-15]: _executeSwapNoApprove reverts if tokenIn or tokenOut are not allowed
function test_AA_15_executeSwap_reverts_if_tokenIn_or_tokenOut_are_not_allowed() public {
_openTestCreditAccount();

address TOKEN = address(0xdead);
bytes memory DUMB_CALLDATA = abi.encodeWithSignature("hello(string)", "world");

// ti == 0 => bad tokenOut, ti == 1 => bad tokenIn
// sa == 0 => no approve, sa == 1 => safe approve
for (uint256 ti; ti < 2; ++ti) {
for (uint256 sa; sa < 2; ++sa) {
bytes memory callData;
if (sa == 1) {
callData = abi.encodeCall(
adapterMock.executeSwapSafeApprove,
(ti == 1 ? TOKEN : dai, ti == 1 ? dai : TOKEN, DUMB_CALLDATA, false)
);
} else {
callData = abi.encodeCall(
adapterMock.executeSwapNoApprove,
(ti == 1 ? TOKEN : dai, ti == 1 ? dai : TOKEN, DUMB_CALLDATA, false)
);
}

if (sa == 0 && ti == 1) {
evm.expectRevert(abi.encodeWithSelector(IAdapterExceptions.TokenIsNotInAllowedList.selector, TOKEN));
} else {
evm.expectRevert(TokenNotAllowedException.selector);
}

evm.prank(USER);
creditFacade.multicall(multicallBuilder(MultiCall({target: address(adapterMock), callData: callData})));
}
}
}
}

0 comments on commit 6988e65

Please sign in to comment.