Use better types than address

Fixes ABDK CVF-6, CVF-7, CVF-16, CVF-17, CVF-31 and CVF-32.
This commit is contained in:
Jason Raymond Bell 2021-05-20 16:50:20 +01:00
parent bf7b19a181
commit d8b8d50de8
3 changed files with 63 additions and 45 deletions

View File

@ -21,6 +21,8 @@ import {FlashLoanReceiverBase} from '../flashloan/base/FlashLoanReceiverBase.sol
abstract contract BaseParaSwapAdapter is FlashLoanReceiverBase, Ownable { abstract contract BaseParaSwapAdapter is FlashLoanReceiverBase, Ownable {
using SafeMath for uint256; using SafeMath for uint256;
using SafeERC20 for IERC20; using SafeERC20 for IERC20;
using SafeERC20 for IERC20Detailed;
using SafeERC20 for IERC20WithPermit;
struct PermitSignature { struct PermitSignature {
uint256 amount; uint256 amount;
@ -56,8 +58,8 @@ abstract contract BaseParaSwapAdapter is FlashLoanReceiverBase, Ownable {
* @dev Get the decimals of an asset * @dev Get the decimals of an asset
* @return number of decimals of the asset * @return number of decimals of the asset
*/ */
function _getDecimals(address asset) internal view returns (uint8) { function _getDecimals(IERC20Detailed asset) internal view returns (uint8) {
uint8 decimals = IERC20Detailed(asset).decimals(); uint8 decimals = asset.decimals();
// Ensure 10**decimals won't overflow a uint256 // Ensure 10**decimals won't overflow a uint256
require(decimals <= 77, 'TOO_MANY_DECIMALS_ON_TOKEN'); require(decimals <= 77, 'TOO_MANY_DECIMALS_ON_TOKEN');
return decimals; return decimals;
@ -81,14 +83,14 @@ abstract contract BaseParaSwapAdapter is FlashLoanReceiverBase, Ownable {
*/ */
function _pullATokenAndWithdraw( function _pullATokenAndWithdraw(
address reserve, address reserve,
address reserveAToken, IERC20WithPermit reserveAToken,
address user, address user,
uint256 amount, uint256 amount,
PermitSignature memory permitSignature PermitSignature memory permitSignature
) internal { ) internal {
// If deadline is set to zero, assume there is no signature for permit // If deadline is set to zero, assume there is no signature for permit
if (permitSignature.deadline != 0) { if (permitSignature.deadline != 0) {
IERC20WithPermit(reserveAToken).permit( reserveAToken.permit(
user, user,
address(this), address(this),
permitSignature.amount, permitSignature.amount,
@ -100,7 +102,7 @@ abstract contract BaseParaSwapAdapter is FlashLoanReceiverBase, Ownable {
} }
// transfer from user to adapter // transfer from user to adapter
IERC20(reserveAToken).safeTransferFrom(user, address(this), amount); reserveAToken.safeTransferFrom(user, address(this), amount);
// withdraw reserve // withdraw reserve
require( require(

View File

@ -6,7 +6,7 @@ import {BaseParaSwapAdapter} from './BaseParaSwapAdapter.sol';
import {PercentageMath} from '../protocol/libraries/math/PercentageMath.sol'; import {PercentageMath} from '../protocol/libraries/math/PercentageMath.sol';
import {IParaSwapAugustus} from '../interfaces/IParaSwapAugustus.sol'; import {IParaSwapAugustus} from '../interfaces/IParaSwapAugustus.sol';
import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.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 * @title BaseParaSwapSellAdapter
@ -36,9 +36,9 @@ abstract contract BaseParaSwapSellAdapter is BaseParaSwapAdapter {
function _sellOnParaSwap( function _sellOnParaSwap(
uint256 fromAmountOffset, uint256 fromAmountOffset,
bytes memory swapCalldata, bytes memory swapCalldata,
address augustus, IParaSwapAugustus augustus,
address assetToSwapFrom, IERC20Detailed assetToSwapFrom,
address assetToSwapTo, IERC20Detailed assetToSwapTo,
uint256 amountToSwap, uint256 amountToSwap,
uint256 minAmountToReceive uint256 minAmountToReceive
) internal returns (uint256 amountReceived) { ) internal returns (uint256 amountReceived) {
@ -46,8 +46,8 @@ abstract contract BaseParaSwapSellAdapter is BaseParaSwapAdapter {
uint256 fromAssetDecimals = _getDecimals(assetToSwapFrom); uint256 fromAssetDecimals = _getDecimals(assetToSwapFrom);
uint256 toAssetDecimals = _getDecimals(assetToSwapTo); uint256 toAssetDecimals = _getDecimals(assetToSwapTo);
uint256 fromAssetPrice = _getPrice(assetToSwapFrom); uint256 fromAssetPrice = _getPrice(address(assetToSwapFrom));
uint256 toAssetPrice = _getPrice(assetToSwapTo); uint256 toAssetPrice = _getPrice(address(assetToSwapTo));
uint256 expectedMinAmountOut = uint256 expectedMinAmountOut =
amountToSwap amountToSwap
@ -58,13 +58,13 @@ abstract contract BaseParaSwapSellAdapter is BaseParaSwapAdapter {
require(expectedMinAmountOut <= minAmountToReceive, 'MIN_AMOUNT_EXCEEDS_MAX_SLIPPAGE'); 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'); 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(); address tokenTransferProxy = augustus.getTokenTransferProxy();
IERC20(assetToSwapFrom).safeApprove(tokenTransferProxy, 0); assetToSwapFrom.safeApprove(tokenTransferProxy, 0);
IERC20(assetToSwapFrom).safeApprove(tokenTransferProxy, amountToSwap); assetToSwapFrom.safeApprove(tokenTransferProxy, amountToSwap);
if (fromAmountOffset != 0) { if (fromAmountOffset != 0) {
// Ensure 256 bit (32 bytes) fromAmount value is within bounds of the // 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) mstore(add(swapCalldata, add(fromAmountOffset, 32)), amountToSwap)
} }
} }
(bool success,) = augustus.call(swapCalldata); (bool success,) = address(augustus).call(swapCalldata);
if (!success) { if (!success) {
// Copy revert reason from call // Copy revert reason from call
assembly { assembly {
@ -87,10 +87,15 @@ abstract contract BaseParaSwapSellAdapter is BaseParaSwapAdapter {
revert(0, returndatasize()) revert(0, returndatasize())
} }
} }
require(IERC20(assetToSwapFrom).balanceOf(address(this)) == balanceBeforeAssetFrom - amountToSwap, 'WRONG_BALANCE_AFTER_SWAP'); require(assetToSwapFrom.balanceOf(address(this)) == balanceBeforeAssetFrom - amountToSwap, 'WRONG_BALANCE_AFTER_SWAP');
amountReceived = IERC20(assetToSwapTo).balanceOf(address(this)).sub(balanceBeforeAssetTo); amountReceived = assetToSwapTo.balanceOf(address(this)).sub(balanceBeforeAssetTo);
require(amountReceived >= minAmountToReceive, 'INSUFFICIENT_AMOUNT_RECEIVED'); require(amountReceived >= minAmountToReceive, 'INSUFFICIENT_AMOUNT_RECEIVED');
emit Swapped(assetToSwapFrom, assetToSwapTo, amountToSwap, amountReceived); emit Swapped(
address(assetToSwapFrom),
address(assetToSwapTo),
amountToSwap,
amountReceived
);
} }
} }

View File

@ -4,7 +4,9 @@ pragma experimental ABIEncoderV2;
import {BaseParaSwapSellAdapter} from './BaseParaSwapSellAdapter.sol'; import {BaseParaSwapSellAdapter} from './BaseParaSwapSellAdapter.sol';
import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.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 * @title ParaSwapLiquiditySwapAdapter
@ -50,15 +52,22 @@ contract ParaSwapLiquiditySwapAdapter is BaseParaSwapSellAdapter {
uint256 flashLoanAmount = amounts[0]; uint256 flashLoanAmount = amounts[0];
uint256 premium = premiums[0]; uint256 premium = premiums[0];
address initiatorLocal = initiator; address initiatorLocal = initiator;
address assetToSwapFrom = assets[0]; IERC20Detailed assetToSwapFrom = IERC20Detailed(assets[0]);
( (
address assetToSwapTo, IERC20Detailed assetToSwapTo,
uint256 minAmountToReceive, uint256 minAmountToReceive,
uint256 swapAllBalanceOffset, uint256 swapAllBalanceOffset,
bytes memory swapCalldata, bytes memory swapCalldata,
address augustus, IParaSwapAugustus augustus,
PermitSignature memory permitParams PermitSignature memory permitParams
) = abi.decode(params, (address, uint256, uint256, bytes, address, PermitSignature)); ) = abi.decode(params, (
IERC20Detailed,
uint256,
uint256,
bytes,
IParaSwapAugustus,
PermitSignature
));
_swapLiquidity( _swapLiquidity(
swapAllBalanceOffset, swapAllBalanceOffset,
@ -90,25 +99,26 @@ contract ParaSwapLiquiditySwapAdapter is BaseParaSwapSellAdapter {
* @param permitParams Struct containing the permit signatures, set to all zeroes if not used * @param permitParams Struct containing the permit signatures, set to all zeroes if not used
*/ */
function swapAndDeposit( function swapAndDeposit(
address assetToSwapFrom, IERC20Detailed assetToSwapFrom,
address assetToSwapTo, IERC20Detailed assetToSwapTo,
uint256 amountToSwap, uint256 amountToSwap,
uint256 minAmountToReceive, uint256 minAmountToReceive,
uint256 swapAllBalanceOffset, uint256 swapAllBalanceOffset,
bytes calldata swapCalldata, bytes calldata swapCalldata,
address augustus, IParaSwapAugustus augustus,
PermitSignature calldata permitParams PermitSignature calldata permitParams
) external { ) external {
address aToken = _getReserveData(assetToSwapFrom).aTokenAddress; IERC20WithPermit aToken =
IERC20WithPermit(_getReserveData(address(assetToSwapFrom)).aTokenAddress);
if (swapAllBalanceOffset != 0) { if (swapAllBalanceOffset != 0) {
uint256 balance = IERC20(aToken).balanceOf(msg.sender); uint256 balance = aToken.balanceOf(msg.sender);
require(balance <= amountToSwap, 'INSUFFICIENT_AMOUNT_TO_SWAP'); require(balance <= amountToSwap, 'INSUFFICIENT_AMOUNT_TO_SWAP');
amountToSwap = balance; amountToSwap = balance;
} }
_pullATokenAndWithdraw( _pullATokenAndWithdraw(
assetToSwapFrom, address(assetToSwapFrom),
aToken, aToken,
msg.sender, msg.sender,
amountToSwap, amountToSwap,
@ -125,9 +135,9 @@ contract ParaSwapLiquiditySwapAdapter is BaseParaSwapSellAdapter {
minAmountToReceive minAmountToReceive
); );
IERC20(assetToSwapTo).safeApprove(address(LENDING_POOL), 0); assetToSwapTo.safeApprove(address(LENDING_POOL), 0);
IERC20(assetToSwapTo).safeApprove(address(LENDING_POOL), amountReceived); assetToSwapTo.safeApprove(address(LENDING_POOL), amountReceived);
LENDING_POOL.deposit(assetToSwapTo, amountReceived, msg.sender, 0); LENDING_POOL.deposit(address(assetToSwapTo), amountReceived, msg.sender, 0);
} }
/** /**
@ -146,19 +156,20 @@ contract ParaSwapLiquiditySwapAdapter is BaseParaSwapSellAdapter {
function _swapLiquidity ( function _swapLiquidity (
uint256 swapAllBalanceOffset, uint256 swapAllBalanceOffset,
bytes memory swapCalldata, bytes memory swapCalldata,
address augustus, IParaSwapAugustus augustus,
PermitSignature memory permitParams, PermitSignature memory permitParams,
uint256 flashLoanAmount, uint256 flashLoanAmount,
uint256 premium, uint256 premium,
address initiator, address initiator,
address assetToSwapFrom, IERC20Detailed assetToSwapFrom,
address assetToSwapTo, IERC20Detailed assetToSwapTo,
uint256 minAmountToReceive uint256 minAmountToReceive
) internal { ) internal {
address aToken = _getReserveData(assetToSwapFrom).aTokenAddress; IERC20WithPermit aToken =
IERC20WithPermit(_getReserveData(address(assetToSwapFrom)).aTokenAddress);
uint256 amountToSwap = flashLoanAmount; uint256 amountToSwap = flashLoanAmount;
uint256 balance = IERC20(aToken).balanceOf(initiator); uint256 balance = aToken.balanceOf(initiator);
if (swapAllBalanceOffset != 0) { if (swapAllBalanceOffset != 0) {
uint256 balanceToSwap = balance.sub(premium); uint256 balanceToSwap = balance.sub(premium);
require(balanceToSwap <= amountToSwap, 'INSUFFICIENT_AMOUNT_TO_SWAP'); require(balanceToSwap <= amountToSwap, 'INSUFFICIENT_AMOUNT_TO_SWAP');
@ -177,12 +188,12 @@ contract ParaSwapLiquiditySwapAdapter is BaseParaSwapSellAdapter {
minAmountToReceive minAmountToReceive
); );
IERC20(assetToSwapTo).safeApprove(address(LENDING_POOL), 0); assetToSwapTo.safeApprove(address(LENDING_POOL), 0);
IERC20(assetToSwapTo).safeApprove(address(LENDING_POOL), amountReceived); assetToSwapTo.safeApprove(address(LENDING_POOL), amountReceived);
LENDING_POOL.deposit(assetToSwapTo, amountReceived, initiator, 0); LENDING_POOL.deposit(address(assetToSwapTo), amountReceived, initiator, 0);
_pullATokenAndWithdraw( _pullATokenAndWithdraw(
assetToSwapFrom, address(assetToSwapFrom),
aToken, aToken,
initiator, initiator,
amountToSwap.add(premium), amountToSwap.add(premium),
@ -190,7 +201,7 @@ contract ParaSwapLiquiditySwapAdapter is BaseParaSwapSellAdapter {
); );
// Repay flash loan // Repay flash loan
IERC20(assetToSwapFrom).safeApprove(address(LENDING_POOL), 0); assetToSwapFrom.safeApprove(address(LENDING_POOL), 0);
IERC20(assetToSwapFrom).safeApprove(address(LENDING_POOL), flashLoanAmount.add(premium)); assetToSwapFrom.safeApprove(address(LENDING_POOL), flashLoanAmount.add(premium));
} }
} }