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 {
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(

View File

@ -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
);
}
}

View File

@ -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));
}
}