diff --git a/contracts/adapters/BaseParaSwapAdapter.sol b/contracts/adapters/BaseParaSwapAdapter.sol index d06e9ec5..9b84dd93 100644 --- a/contracts/adapters/BaseParaSwapAdapter.sol +++ b/contracts/adapters/BaseParaSwapAdapter.sol @@ -21,6 +21,8 @@ import {FlashLoanReceiverBase} from '../flashloan/base/FlashLoanReceiverBase.sol abstract contract BaseParaSwapAdapter is FlashLoanReceiverBase, Ownable { using SafeMath for uint256; using SafeERC20 for IERC20; + using SafeERC20 for IERC20Detailed; + using SafeERC20 for IERC20WithPermit; struct PermitSignature { uint256 amount; @@ -56,8 +58,8 @@ abstract contract BaseParaSwapAdapter is FlashLoanReceiverBase, Ownable { * @dev Get the decimals of an asset * @return number of decimals of the asset */ - function _getDecimals(address asset) internal view returns (uint8) { - uint8 decimals = IERC20Detailed(asset).decimals(); + function _getDecimals(IERC20Detailed asset) internal view returns (uint8) { + uint8 decimals = asset.decimals(); // Ensure 10**decimals won't overflow a uint256 require(decimals <= 77, 'TOO_MANY_DECIMALS_ON_TOKEN'); return decimals; @@ -81,14 +83,14 @@ abstract contract BaseParaSwapAdapter is FlashLoanReceiverBase, Ownable { */ function _pullATokenAndWithdraw( address reserve, - address reserveAToken, + IERC20WithPermit reserveAToken, address user, uint256 amount, PermitSignature memory permitSignature ) internal { // If deadline is set to zero, assume there is no signature for permit if (permitSignature.deadline != 0) { - IERC20WithPermit(reserveAToken).permit( + reserveAToken.permit( user, address(this), permitSignature.amount, @@ -100,7 +102,7 @@ abstract contract BaseParaSwapAdapter is FlashLoanReceiverBase, Ownable { } // transfer from user to adapter - IERC20(reserveAToken).safeTransferFrom(user, address(this), amount); + reserveAToken.safeTransferFrom(user, address(this), amount); // withdraw reserve require( diff --git a/contracts/adapters/BaseParaSwapSellAdapter.sol b/contracts/adapters/BaseParaSwapSellAdapter.sol index c433f3f7..5b750287 100644 --- a/contracts/adapters/BaseParaSwapSellAdapter.sol +++ b/contracts/adapters/BaseParaSwapSellAdapter.sol @@ -6,7 +6,7 @@ import {BaseParaSwapAdapter} from './BaseParaSwapAdapter.sol'; import {PercentageMath} from '../protocol/libraries/math/PercentageMath.sol'; import {IParaSwapAugustus} from '../interfaces/IParaSwapAugustus.sol'; import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol'; -import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol'; +import {IERC20Detailed} from '../dependencies/openzeppelin/contracts/IERC20Detailed.sol'; /** * @title BaseParaSwapSellAdapter @@ -36,9 +36,9 @@ abstract contract BaseParaSwapSellAdapter is BaseParaSwapAdapter { function _sellOnParaSwap( uint256 fromAmountOffset, bytes memory swapCalldata, - address augustus, - address assetToSwapFrom, - address assetToSwapTo, + IParaSwapAugustus augustus, + IERC20Detailed assetToSwapFrom, + IERC20Detailed assetToSwapTo, uint256 amountToSwap, uint256 minAmountToReceive ) internal returns (uint256 amountReceived) { @@ -46,8 +46,8 @@ abstract contract BaseParaSwapSellAdapter is BaseParaSwapAdapter { uint256 fromAssetDecimals = _getDecimals(assetToSwapFrom); uint256 toAssetDecimals = _getDecimals(assetToSwapTo); - uint256 fromAssetPrice = _getPrice(assetToSwapFrom); - uint256 toAssetPrice = _getPrice(assetToSwapTo); + uint256 fromAssetPrice = _getPrice(address(assetToSwapFrom)); + uint256 toAssetPrice = _getPrice(address(assetToSwapTo)); uint256 expectedMinAmountOut = amountToSwap @@ -58,13 +58,13 @@ abstract contract BaseParaSwapSellAdapter is BaseParaSwapAdapter { require(expectedMinAmountOut <= minAmountToReceive, 'MIN_AMOUNT_EXCEEDS_MAX_SLIPPAGE'); } - uint256 balanceBeforeAssetFrom = IERC20(assetToSwapFrom).balanceOf(address(this)); + uint256 balanceBeforeAssetFrom = assetToSwapFrom.balanceOf(address(this)); require(balanceBeforeAssetFrom >= amountToSwap, 'INSUFFICIENT_BALANCE_BEFORE_SWAP'); - uint256 balanceBeforeAssetTo = IERC20(assetToSwapTo).balanceOf(address(this)); + uint256 balanceBeforeAssetTo = assetToSwapTo.balanceOf(address(this)); - address tokenTransferProxy = IParaSwapAugustus(augustus).getTokenTransferProxy(); - IERC20(assetToSwapFrom).safeApprove(tokenTransferProxy, 0); - IERC20(assetToSwapFrom).safeApprove(tokenTransferProxy, amountToSwap); + address tokenTransferProxy = augustus.getTokenTransferProxy(); + assetToSwapFrom.safeApprove(tokenTransferProxy, 0); + assetToSwapFrom.safeApprove(tokenTransferProxy, amountToSwap); if (fromAmountOffset != 0) { // Ensure 256 bit (32 bytes) fromAmount value is within bounds of the @@ -79,7 +79,7 @@ abstract contract BaseParaSwapSellAdapter is BaseParaSwapAdapter { mstore(add(swapCalldata, add(fromAmountOffset, 32)), amountToSwap) } } - (bool success,) = augustus.call(swapCalldata); + (bool success,) = address(augustus).call(swapCalldata); if (!success) { // Copy revert reason from call assembly { @@ -87,10 +87,15 @@ abstract contract BaseParaSwapSellAdapter is BaseParaSwapAdapter { revert(0, returndatasize()) } } - require(IERC20(assetToSwapFrom).balanceOf(address(this)) == balanceBeforeAssetFrom - amountToSwap, 'WRONG_BALANCE_AFTER_SWAP'); - amountReceived = IERC20(assetToSwapTo).balanceOf(address(this)).sub(balanceBeforeAssetTo); + require(assetToSwapFrom.balanceOf(address(this)) == balanceBeforeAssetFrom - amountToSwap, 'WRONG_BALANCE_AFTER_SWAP'); + amountReceived = assetToSwapTo.balanceOf(address(this)).sub(balanceBeforeAssetTo); require(amountReceived >= minAmountToReceive, 'INSUFFICIENT_AMOUNT_RECEIVED'); - emit Swapped(assetToSwapFrom, assetToSwapTo, amountToSwap, amountReceived); + emit Swapped( + address(assetToSwapFrom), + address(assetToSwapTo), + amountToSwap, + amountReceived + ); } } diff --git a/contracts/adapters/ParaSwapLiquiditySwapAdapter.sol b/contracts/adapters/ParaSwapLiquiditySwapAdapter.sol index a80c9df9..338fa09e 100644 --- a/contracts/adapters/ParaSwapLiquiditySwapAdapter.sol +++ b/contracts/adapters/ParaSwapLiquiditySwapAdapter.sol @@ -4,7 +4,9 @@ pragma experimental ABIEncoderV2; import {BaseParaSwapSellAdapter} from './BaseParaSwapSellAdapter.sol'; import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol'; -import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol'; +import {IERC20Detailed} from '../dependencies/openzeppelin/contracts/IERC20Detailed.sol'; +import {IERC20WithPermit} from '../interfaces/IERC20WithPermit.sol'; +import {IParaSwapAugustus} from '../interfaces/IParaSwapAugustus.sol'; /** * @title ParaSwapLiquiditySwapAdapter @@ -50,15 +52,22 @@ contract ParaSwapLiquiditySwapAdapter is BaseParaSwapSellAdapter { uint256 flashLoanAmount = amounts[0]; uint256 premium = premiums[0]; address initiatorLocal = initiator; - address assetToSwapFrom = assets[0]; + IERC20Detailed assetToSwapFrom = IERC20Detailed(assets[0]); ( - address assetToSwapTo, + IERC20Detailed assetToSwapTo, uint256 minAmountToReceive, uint256 swapAllBalanceOffset, bytes memory swapCalldata, - address augustus, + IParaSwapAugustus augustus, PermitSignature memory permitParams - ) = abi.decode(params, (address, uint256, uint256, bytes, address, PermitSignature)); + ) = abi.decode(params, ( + IERC20Detailed, + uint256, + uint256, + bytes, + IParaSwapAugustus, + PermitSignature + )); _swapLiquidity( swapAllBalanceOffset, @@ -90,25 +99,26 @@ contract ParaSwapLiquiditySwapAdapter is BaseParaSwapSellAdapter { * @param permitParams Struct containing the permit signatures, set to all zeroes if not used */ function swapAndDeposit( - address assetToSwapFrom, - address assetToSwapTo, + IERC20Detailed assetToSwapFrom, + IERC20Detailed assetToSwapTo, uint256 amountToSwap, uint256 minAmountToReceive, uint256 swapAllBalanceOffset, bytes calldata swapCalldata, - address augustus, + IParaSwapAugustus augustus, PermitSignature calldata permitParams ) external { - address aToken = _getReserveData(assetToSwapFrom).aTokenAddress; + IERC20WithPermit aToken = + IERC20WithPermit(_getReserveData(address(assetToSwapFrom)).aTokenAddress); if (swapAllBalanceOffset != 0) { - uint256 balance = IERC20(aToken).balanceOf(msg.sender); + uint256 balance = aToken.balanceOf(msg.sender); require(balance <= amountToSwap, 'INSUFFICIENT_AMOUNT_TO_SWAP'); amountToSwap = balance; } _pullATokenAndWithdraw( - assetToSwapFrom, + address(assetToSwapFrom), aToken, msg.sender, amountToSwap, @@ -125,9 +135,9 @@ contract ParaSwapLiquiditySwapAdapter is BaseParaSwapSellAdapter { minAmountToReceive ); - IERC20(assetToSwapTo).safeApprove(address(LENDING_POOL), 0); - IERC20(assetToSwapTo).safeApprove(address(LENDING_POOL), amountReceived); - LENDING_POOL.deposit(assetToSwapTo, amountReceived, msg.sender, 0); + assetToSwapTo.safeApprove(address(LENDING_POOL), 0); + assetToSwapTo.safeApprove(address(LENDING_POOL), amountReceived); + LENDING_POOL.deposit(address(assetToSwapTo), amountReceived, msg.sender, 0); } /** @@ -146,19 +156,20 @@ contract ParaSwapLiquiditySwapAdapter is BaseParaSwapSellAdapter { function _swapLiquidity ( uint256 swapAllBalanceOffset, bytes memory swapCalldata, - address augustus, + IParaSwapAugustus augustus, PermitSignature memory permitParams, uint256 flashLoanAmount, uint256 premium, address initiator, - address assetToSwapFrom, - address assetToSwapTo, + IERC20Detailed assetToSwapFrom, + IERC20Detailed assetToSwapTo, uint256 minAmountToReceive ) internal { - address aToken = _getReserveData(assetToSwapFrom).aTokenAddress; + IERC20WithPermit aToken = + IERC20WithPermit(_getReserveData(address(assetToSwapFrom)).aTokenAddress); uint256 amountToSwap = flashLoanAmount; - uint256 balance = IERC20(aToken).balanceOf(initiator); + uint256 balance = aToken.balanceOf(initiator); if (swapAllBalanceOffset != 0) { uint256 balanceToSwap = balance.sub(premium); require(balanceToSwap <= amountToSwap, 'INSUFFICIENT_AMOUNT_TO_SWAP'); @@ -177,12 +188,12 @@ contract ParaSwapLiquiditySwapAdapter is BaseParaSwapSellAdapter { minAmountToReceive ); - IERC20(assetToSwapTo).safeApprove(address(LENDING_POOL), 0); - IERC20(assetToSwapTo).safeApprove(address(LENDING_POOL), amountReceived); - LENDING_POOL.deposit(assetToSwapTo, amountReceived, initiator, 0); + assetToSwapTo.safeApprove(address(LENDING_POOL), 0); + assetToSwapTo.safeApprove(address(LENDING_POOL), amountReceived); + LENDING_POOL.deposit(address(assetToSwapTo), amountReceived, initiator, 0); _pullATokenAndWithdraw( - assetToSwapFrom, + address(assetToSwapFrom), aToken, initiator, amountToSwap.add(premium), @@ -190,7 +201,7 @@ contract ParaSwapLiquiditySwapAdapter is BaseParaSwapSellAdapter { ); // Repay flash loan - IERC20(assetToSwapFrom).safeApprove(address(LENDING_POOL), 0); - IERC20(assetToSwapFrom).safeApprove(address(LENDING_POOL), flashLoanAmount.add(premium)); + assetToSwapFrom.safeApprove(address(LENDING_POOL), 0); + assetToSwapFrom.safeApprove(address(LENDING_POOL), flashLoanAmount.add(premium)); } }