ParaSwap adapter for collateral swaps

Complete with unit tests (using a mock AugustusSwapper contract).

Has similar functionality/tests as for existing Uniswap adapter.

Fixed a couple bugs in tests for Uniswap adapters.
This commit is contained in:
Jason Raymond Bell 2021-03-18 15:44:52 +00:00
parent 2708551bcf
commit 242826ded6
17 changed files with 2916 additions and 3 deletions

View File

@ -0,0 +1,124 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
import {SafeMath} from '../dependencies/openzeppelin/contracts/SafeMath.sol';
import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol';
import {IERC20Detailed} from '../dependencies/openzeppelin/contracts/IERC20Detailed.sol';
import {SafeERC20} from '../dependencies/openzeppelin/contracts/SafeERC20.sol';
import {Ownable} from '../dependencies/openzeppelin/contracts/Ownable.sol';
import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol';
import {DataTypes} from '../protocol/libraries/types/DataTypes.sol';
import {IPriceOracleGetter} from '../interfaces/IPriceOracleGetter.sol';
import {IERC20WithPermit} from '../interfaces/IERC20WithPermit.sol';
import {FlashLoanReceiverBase} from '../flashloan/base/FlashLoanReceiverBase.sol';
/**
* @title BaseParaSwapAdapter
* @notice Utility functions for adapters using ParaSwap
* @author Jason Raymond Bell
*/
abstract contract BaseParaSwapAdapter is FlashLoanReceiverBase, Ownable {
using SafeMath for uint256;
using SafeERC20 for IERC20;
struct PermitSignature {
uint256 amount;
uint256 deadline;
uint8 v;
bytes32 r;
bytes32 s;
}
// Max slippage percent allowed
uint256 public constant MAX_SLIPPAGE_PERCENT = 3000; // 30%
IPriceOracleGetter public immutable ORACLE;
event Swapped(address indexed fromAsset, address indexed toAsset, uint256 fromAmount, uint256 receivedAmount);
constructor(
ILendingPoolAddressesProvider addressesProvider
) public FlashLoanReceiverBase(addressesProvider) {
ORACLE = IPriceOracleGetter(addressesProvider.getPriceOracle());
}
/**
* @dev Get the price of the asset from the oracle denominated in eth
* @param asset address
* @return eth price for the asset
*/
function _getPrice(address asset) internal view returns (uint256) {
return ORACLE.getAssetPrice(asset);
}
/**
* @dev Get the decimals of an asset
* @return number of decimals of the asset
*/
function _getDecimals(address asset) internal view returns (uint256) {
return IERC20Detailed(asset).decimals();
}
/**
* @dev Get the aToken associated to the asset
* @return address of the aToken
*/
function _getReserveData(address asset) internal view returns (DataTypes.ReserveData memory) {
return LENDING_POOL.getReserveData(asset);
}
/**
* @dev Pull the ATokens from the user
* @param reserve address of the asset
* @param reserveAToken address of the aToken of the reserve
* @param user address
* @param amount of tokens to be transferred to the contract
* @param permitSignature struct containing the permit signature
*/
function _pullAToken(
address reserve,
address reserveAToken,
address user,
uint256 amount,
PermitSignature memory permitSignature
) internal {
if (_usePermit(permitSignature)) {
IERC20WithPermit(reserveAToken).permit(
user,
address(this),
permitSignature.amount,
permitSignature.deadline,
permitSignature.v,
permitSignature.r,
permitSignature.s
);
}
// transfer from user to adapter
IERC20(reserveAToken).safeTransferFrom(user, address(this), amount);
// withdraw reserve
LENDING_POOL.withdraw(reserve, amount, address(this));
}
/**
* @dev Tells if the permit method should be called by inspecting if there is a valid signature.
* If signature params are set to 0, then permit won't be called.
* @param signature struct containing the permit signature
* @return whether or not permit should be called
*/
function _usePermit(PermitSignature memory signature) internal pure returns (bool) {
return
!(uint256(signature.deadline) == uint256(signature.v) && uint256(signature.deadline) == 0);
}
/**
* @dev Emergency rescue for token stucked on this contract, as failsafe mechanism
* - Funds should never remain in this contract more time than during transactions
* - Only callable by the owner
*/
function rescueTokens(IERC20 token) external onlyOwner {
token.transfer(owner(), token.balanceOf(address(this)));
}
}

View File

@ -0,0 +1,92 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
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';
/**
* @title BaseParaSwapSellAdapter
* @notice Implements the logic for selling tokens on ParaSwap
* @author Jason Raymond Bell
*/
abstract contract BaseParaSwapSellAdapter is BaseParaSwapAdapter {
using PercentageMath for uint256;
constructor(
ILendingPoolAddressesProvider addressesProvider
) public BaseParaSwapAdapter(addressesProvider) {
}
/**
* @dev Swaps a token for another using ParaSwap
* @param fromAmountOffset Offset of fromAmount in Augustus calldata if it should be overwritten, otherwise 0
* @param swapCalldata Calldata for ParaSwap's AugustusSwapper contract
* @param augustus Address of ParaSwap's AugustusSwapper contract
* @param assetToSwapFrom Address of the asset to be swapped from
* @param assetToSwapTo Address of the asset to be swapped to
* @param amountToSwap Amount to be swapped
* @param minAmountToReceive Minimum amount to be received from the swap
* @return amountReceived The amount received from the swap
*/
function _sellOnParaSwap(
uint256 fromAmountOffset,
bytes memory swapCalldata,
address augustus,
address assetToSwapFrom,
address assetToSwapTo,
uint256 amountToSwap,
uint256 minAmountToReceive
) internal returns (uint256 amountReceived) {
{
uint256 fromAssetDecimals = _getDecimals(assetToSwapFrom);
uint256 toAssetDecimals = _getDecimals(assetToSwapTo);
uint256 fromAssetPrice = _getPrice(assetToSwapFrom);
uint256 toAssetPrice = _getPrice(assetToSwapTo);
uint256 expectedMinAmountOut =
amountToSwap
.mul(fromAssetPrice.mul(10**toAssetDecimals))
.div(toAssetPrice.mul(10**fromAssetDecimals))
.percentMul(PercentageMath.PERCENTAGE_FACTOR - MAX_SLIPPAGE_PERCENT);
require(expectedMinAmountOut <= minAmountToReceive, 'MIN_AMOUNT_EXCEEDS_MAX_SLIPPAGE');
}
uint256 balanceBeforeAssetFrom = IERC20(assetToSwapFrom).balanceOf(address(this));
require(balanceBeforeAssetFrom >= amountToSwap, 'INSUFFICIENT_BALANCE_BEFORE_SWAP');
uint256 balanceBeforeAssetTo = IERC20(assetToSwapTo).balanceOf(address(this));
address tokenTransferProxy = IParaSwapAugustus(augustus).getTokenTransferProxy();
IERC20(assetToSwapFrom).safeApprove(tokenTransferProxy, 0);
IERC20(assetToSwapFrom).safeApprove(tokenTransferProxy, amountToSwap);
if (fromAmountOffset != 0) {
require(fromAmountOffset >= 4 &&
fromAmountOffset <= swapCalldata.length.sub(32),
'FROM_AMOUNT_OFFSET_OUT_OF_RANGE');
assembly {
mstore(add(swapCalldata, add(fromAmountOffset, 32)), amountToSwap)
}
}
(bool success,) = augustus.call(swapCalldata);
if (!success) {
// Copy revert reason from call
assembly {
let ptr := mload(0x40)
let size := returndatasize()
returndatacopy(ptr, 0, size)
revert(ptr, size)
}
}
require(IERC20(assetToSwapFrom).balanceOf(address(this)) == balanceBeforeAssetFrom - amountToSwap, 'WRONG_BALANCE_AFTER_SWAP');
amountReceived = IERC20(assetToSwapTo).balanceOf(address(this)).sub(balanceBeforeAssetTo);
require(amountReceived >= minAmountToReceive, 'INSUFFICIENT_AMOUNT_RECEIVED');
emit Swapped(assetToSwapFrom, assetToSwapTo, amountToSwap, amountReceived);
}
}

View File

@ -0,0 +1,191 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
import {BaseParaSwapSellAdapter} from './BaseParaSwapSellAdapter.sol';
import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol';
import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol';
/**
* @title ParaSwapLiquiditySwapAdapter
* @notice Adapter to swap liquidity using ParaSwap.
* @author Jason Raymond Bell
*/
contract ParaSwapLiquiditySwapAdapter is BaseParaSwapSellAdapter {
constructor(
ILendingPoolAddressesProvider addressesProvider
) public BaseParaSwapSellAdapter(addressesProvider) {}
/**
* @dev Swaps the received reserve amount from the flash loan into the asset specified in the params.
* The received funds from the swap are then deposited into the protocol on behalf of the user.
* The user should give this contract allowance to pull the ATokens in order to withdraw the underlying asset and repay the flash loan.
* @param assets Address of the underlying asset to be swapped from
* @param amounts Amount of the flash loan i.e. maximum amount to swap
* @param premiums Fee of the flash loan
* @param initiator Account that initiated the flash loan
* @param params Additional variadic field to include extra params. Expected parameters:
* address assetToSwapTo Address of the underlying asset to be swapped to and deposited
* uint256 minAmountToReceive Min amount to be received from the swap
* uint256 swapAllBalanceOffset Set to offset of fromAmount in Augustus calldata if wanting to swap all balance, otherwise 0
* bytes swapCalldata Calldata for ParaSwap's AugustusSwapper contract
* address augustus Address of ParaSwap's AugustusSwapper contract
* PermitSignature permitParams Struct containing the permit signatures, set to all zeroes if not used
*/
function executeOperation(
address[] calldata assets,
uint256[] calldata amounts,
uint256[] calldata premiums,
address initiator,
bytes calldata params
) external override returns (bool) {
require(msg.sender == address(LENDING_POOL), 'CALLER_MUST_BE_LENDING_POOL');
require(assets.length == 1, 'FLASHLOAN_MULTIPLE_ASSETS_NOT_SUPPORTED');
uint256 flashLoanAmount = amounts[0];
uint256 premium = premiums[0];
address initiatorLocal = initiator;
address assetToSwapFrom = assets[0];
(
address assetToSwapTo,
uint256 minAmountToReceive,
uint256 swapAllBalanceOffset,
bytes memory swapCalldata,
address augustus,
PermitSignature memory permitParams
) = abi.decode(params, (address, uint256, uint256, bytes, address, PermitSignature));
_swapLiquidity(
swapAllBalanceOffset,
swapCalldata,
augustus,
permitParams,
flashLoanAmount,
premium,
initiatorLocal,
assetToSwapFrom,
assetToSwapTo,
minAmountToReceive
);
return true;
}
/**
* @dev Swaps an amount of an asset to another and deposits the new asset amount on behalf of the user without using a flash loan.
* This method can be used when the temporary transfer of the collateral asset to this contract does not affect the user position.
* The user should give this contract allowance to pull the ATokens in order to withdraw the underlying asset and perform the swap.
* @param assetToSwapFrom Address of the underlying asset to be swapped from
* @param assetToSwapTo Address of the underlying asset to be swapped to and deposited
* @param amountToSwap Amount to be swapped, or maximum amount when swapping all balance
* @param minAmountToReceive Minimum amount to be received from the swap
* @param swapAllBalanceOffset Set to offset of fromAmount in Augustus calldata if wanting to swap all balance, otherwise 0
* @param swapCalldata Calldata for ParaSwap's AugustusSwapper contract
* @param augustus Address of ParaSwap's AugustusSwapper contract
* @param permitParams Struct containing the permit signatures, set to all zeroes if not used
*/
function swapAndDeposit(
address assetToSwapFrom,
address assetToSwapTo,
uint256 amountToSwap,
uint256 minAmountToReceive,
uint256 swapAllBalanceOffset,
bytes calldata swapCalldata,
address augustus,
PermitSignature calldata permitParams
) external {
address aToken = _getReserveData(assetToSwapFrom).aTokenAddress;
if (swapAllBalanceOffset != 0) {
uint256 balance = IERC20(aToken).balanceOf(msg.sender);
require(balance <= amountToSwap, 'INSUFFICIENT_AMOUNT_TO_SWAP');
amountToSwap = balance;
}
_pullAToken(
assetToSwapFrom,
aToken,
msg.sender,
amountToSwap,
permitParams
);
uint256 amountReceived = _sellOnParaSwap(
swapAllBalanceOffset,
swapCalldata,
augustus,
assetToSwapFrom,
assetToSwapTo,
amountToSwap,
minAmountToReceive
);
IERC20(assetToSwapTo).safeApprove(address(LENDING_POOL), 0);
IERC20(assetToSwapTo).safeApprove(address(LENDING_POOL), amountReceived);
LENDING_POOL.deposit(assetToSwapTo, amountReceived, msg.sender, 0);
}
/**
* @dev Swaps an amount of an asset to another and deposits the funds on behalf of the initiator.
* @param swapAllBalanceOffset Set to offset of fromAmount in Augustus calldata if wanting to swap all balance, otherwise 0
* @param swapCalldata Calldata for ParaSwap's AugustusSwapper contract
* @param augustus Address of ParaSwap's AugustusSwapper contract
* @param permitParams Struct containing the permit signatures, set to all zeroes if not used
* @param flashLoanAmount Amount of the flash loan i.e. maximum amount to swap
* @param premium Fee of the flash loan
* @param initiator Account that initiated the flash loan
* @param assetToSwapFrom Address of the underyling asset to be swapped from
* @param assetToSwapTo Address of the underlying asset to be swapped to and deposited
* @param minAmountToReceive Min amount to be received from the swap
*/
function _swapLiquidity (
uint256 swapAllBalanceOffset,
bytes memory swapCalldata,
address augustus,
PermitSignature memory permitParams,
uint256 flashLoanAmount,
uint256 premium,
address initiator,
address assetToSwapFrom,
address assetToSwapTo,
uint256 minAmountToReceive
) internal {
address aToken = _getReserveData(assetToSwapFrom).aTokenAddress;
uint256 amountToSwap = flashLoanAmount;
uint256 balance = IERC20(aToken).balanceOf(initiator);
if (swapAllBalanceOffset != 0) {
uint256 balanceToSwap = balance.sub(premium);
require(balanceToSwap <= amountToSwap, 'INSUFFICIENT_AMOUNT_TO_SWAP');
amountToSwap = balanceToSwap;
} else {
require(balance >= amountToSwap.add(premium), 'INSUFFICIENT_ATOKEN_BALANCE');
}
uint256 amountReceived = _sellOnParaSwap(
swapAllBalanceOffset,
swapCalldata,
augustus,
assetToSwapFrom,
assetToSwapTo,
amountToSwap,
minAmountToReceive
);
IERC20(assetToSwapTo).safeApprove(address(LENDING_POOL), 0);
IERC20(assetToSwapTo).safeApprove(address(LENDING_POOL), amountReceived);
LENDING_POOL.deposit(assetToSwapTo, amountReceived, initiator, 0);
_pullAToken(
assetToSwapFrom,
aToken,
initiator,
amountToSwap.add(premium),
permitParams
);
// Repay flash loan
IERC20(assetToSwapFrom).safeApprove(address(LENDING_POOL), 0);
IERC20(assetToSwapFrom).safeApprove(address(LENDING_POOL), flashLoanAmount.add(premium));
}
}

View File

@ -0,0 +1,7 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
interface IParaSwapAugustus {
function getTokenTransferProxy() external view returns (address);
}

View File

@ -0,0 +1,59 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
import {IParaSwapAugustus} from '../../interfaces/IParaSwapAugustus.sol';
import {MockParaSwapTokenTransferProxy} from './MockParaSwapTokenTransferProxy.sol';
import {IERC20} from '../../dependencies/openzeppelin/contracts/IERC20.sol';
import {MintableERC20} from '../tokens/MintableERC20.sol';
contract MockParaSwapAugustus is IParaSwapAugustus {
MockParaSwapTokenTransferProxy _tokenTransferProxy;
bool _expectingSwap;
address _expectedFromToken;
address _expectedToToken;
uint256 _expectedFromAmountMin;
uint256 _expectedFromAmountMax;
uint256 _receivedAmount;
constructor() public {
_tokenTransferProxy = new MockParaSwapTokenTransferProxy();
}
function getTokenTransferProxy() external view override returns (address) {
return address(_tokenTransferProxy);
}
function expectSwap(
address fromToken,
address toToken,
uint256 fromAmountMin,
uint256 fromAmountMax,
uint256 receivedAmount
) external {
_expectingSwap = true;
_expectedFromToken = fromToken;
_expectedToToken = toToken;
_expectedFromAmountMin = fromAmountMin;
_expectedFromAmountMax = fromAmountMax;
_receivedAmount = receivedAmount;
}
function swap(
address fromToken,
address toToken,
uint256 fromAmount,
uint256 toAmount
) external returns (uint256) {
require(_expectingSwap, 'Not expecting swap');
require(fromToken == _expectedFromToken, 'Unexpected from token');
require(toToken == _expectedToToken, 'Unexpected to token');
require(fromAmount >= _expectedFromAmountMin && fromAmount <= _expectedFromAmountMax, 'From amount out of range');
require(_receivedAmount >= toAmount, 'Received amount of tokens are less than expected');
_tokenTransferProxy.transferFrom(fromToken, msg.sender, address(this), fromAmount);
MintableERC20(toToken).mint(_receivedAmount);
IERC20(toToken).transfer(msg.sender, _receivedAmount);
_expectingSwap = false;
return _receivedAmount;
}
}

View File

@ -0,0 +1,17 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
import {Ownable} from '../../dependencies/openzeppelin/contracts/Ownable.sol';
import {IERC20} from '../../dependencies/openzeppelin/contracts/IERC20.sol';
contract MockParaSwapTokenTransferProxy is Ownable {
function transferFrom(
address token,
address from,
address to,
uint256 amount
) external onlyOwner {
IERC20(token).transferFrom(from, to, amount);
}
}

View File

@ -36,9 +36,11 @@ import {
MockAggregatorFactory,
MockATokenFactory,
MockFlashLoanReceiverFactory,
MockParaSwapAugustusFactory,
MockStableDebtTokenFactory,
MockVariableDebtTokenFactory,
MockUniswapV2Router02Factory,
ParaSwapLiquiditySwapAdapterFactory,
PriceOracleFactory,
ReserveLogicFactory,
SelfdestructTransferFactory,
@ -537,3 +539,22 @@ export const deployFlashLiquidationAdapter = async (
args,
verify
);
export const deployMockParaSwapAugustus = async (verify?: boolean) =>
withSaveAndVerify(
await new MockParaSwapAugustusFactory(await getFirstSigner()).deploy(),
eContractid.MockParaSwapAugustus,
[],
verify
);
export const deployParaSwapLiquiditySwapAdapter = async (
args: [tEthereumAddress],
verify?: boolean
) =>
withSaveAndVerify(
await new ParaSwapLiquiditySwapAdapterFactory(await getFirstSigner()).deploy(...args),
eContractid.ParaSwapLiquiditySwapAdapter,
args,
verify
);

View File

@ -18,6 +18,8 @@ import {
MockStableDebtTokenFactory,
MockVariableDebtTokenFactory,
MockUniswapV2Router02Factory,
MockParaSwapAugustusFactory,
ParaSwapLiquiditySwapAdapterFactory,
PriceOracleFactory,
ReserveLogicFactory,
SelfdestructTransferFactory,
@ -363,3 +365,19 @@ export const getFlashLiquidationAdapter = async (address?: tEthereumAddress) =>
.address,
await getFirstSigner()
);
export const getMockParaSwapAugustus = async (address?: tEthereumAddress) =>
await MockParaSwapAugustusFactory.connect(
address ||
(await getDb().get(`${eContractid.MockParaSwapAugustus}.${DRE.network.name}`).value())
.address,
await getFirstSigner()
);
export const getParaSwapLiquiditySwapAdapter = async (address?: tEthereumAddress) =>
await ParaSwapLiquiditySwapAdapterFactory.connect(
address ||
(await getDb().get(`${eContractid.ParaSwapLiquiditySwapAdapter}.${DRE.network.name}`).value())
.address,
await getFirstSigner()
);

View File

@ -301,3 +301,35 @@ export const buildFlashLiquidationAdapterParams = (
[collateralAsset, debtAsset, user, debtToCover, useEthPath]
);
};
export const buildParaSwapLiquiditySwapParams = (
assetToSwapTo: tEthereumAddress,
minAmountToReceive: BigNumberish,
swapAllBalanceOffset: BigNumberish,
swapCalldata: string | Buffer,
augustus: tEthereumAddress,
permitAmount: BigNumberish,
deadline: BigNumberish,
v: BigNumberish,
r: string | Buffer,
s: string | Buffer
) => {
return ethers.utils.defaultAbiCoder.encode(
[
'address',
'uint256',
'uint256',
'bytes',
'address',
'tuple(uint256,uint256,uint8,bytes32,bytes32)',
],
[
assetToSwapTo,
minAmountToReceive,
swapAllBalanceOffset,
swapCalldata,
augustus,
[permitAmount, deadline, v, r, s],
]
);
};

View File

@ -71,6 +71,8 @@ export enum eContractid {
UniswapLiquiditySwapAdapter = 'UniswapLiquiditySwapAdapter',
UniswapRepayAdapter = 'UniswapRepayAdapter',
FlashLiquidationAdapter = 'FlashLiquidationAdapter',
MockParaSwapAugustus = 'MockParaSwapAugustus',
ParaSwapLiquiditySwapAdapter = 'ParaSwapLiquiditySwapAdapter',
}
/*

View File

@ -32,6 +32,7 @@
"test-subgraph:scenarios": "hardhat --network hardhatevm_docker test test/__setup.spec.ts test/subgraph-scenarios.spec.ts",
"test-weth": "hardhat test test/__setup.spec.ts test/weth-gateway.spec.ts",
"test-uniswap": "hardhat test test/__setup.spec.ts test/uniswapAdapters*.spec.ts",
"test-paraswap": "hardhat test test/__setup.spec.ts test/paraswapAdapters*.spec.ts",
"test:main:check-list": "MAINNET_FORK=true TS_NODE_TRANSPILE_ONLY=1 hardhat test test/__setup.spec.ts test/mainnet/check-list.spec.ts",
"dev:coverage": "buidler compile --force && buidler coverage --network coverage",
"aave:evm:dev:migration": "npm run compile && hardhat aave:dev",

View File

@ -26,6 +26,8 @@ import {
deployUniswapLiquiditySwapAdapter,
deployUniswapRepayAdapter,
deployFlashLiquidationAdapter,
deployMockParaSwapAugustus,
deployParaSwapLiquiditySwapAdapter,
} from '../helpers/contracts-deployments';
import { Signer } from 'ethers';
import { TokenContractId, eContractid, tEthereumAddress, AavePools } from '../helpers/types';
@ -247,6 +249,10 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => {
await deployUniswapRepayAdapter(adapterParams);
await deployFlashLiquidationAdapter(adapterParams);
await deployMockParaSwapAugustus();
await deployParaSwapLiquiditySwapAdapter([addressesProvider.address]);
await deployWalletBalancerProvider();
await deployWETHGateway([mockTokens.WETH.address, lendingPoolAddress]);

View File

@ -14,6 +14,7 @@ import {
getUniswapLiquiditySwapAdapter,
getUniswapRepayAdapter,
getFlashLiquidationAdapter,
getParaSwapLiquiditySwapAdapter,
} from '../../helpers/contracts-getters';
import { eEthereumNetwork, tEthereumAddress } from '../../helpers/types';
import { LendingPool } from '../../types/LendingPool';
@ -32,6 +33,7 @@ import { LendingPoolAddressesProviderRegistry } from '../../types/LendingPoolAdd
import { getEthersSigners } from '../../helpers/contracts-helpers';
import { UniswapLiquiditySwapAdapter } from '../../types/UniswapLiquiditySwapAdapter';
import { UniswapRepayAdapter } from '../../types/UniswapRepayAdapter';
import { ParaSwapLiquiditySwapAdapter } from '../../types/ParaSwapLiquiditySwapAdapter';
import { getParamPerNetwork } from '../../helpers/contracts-helpers';
import { WETH9Mocked } from '../../types/WETH9Mocked';
import { WETHGateway } from '../../types/WETHGateway';
@ -68,6 +70,7 @@ export interface TestEnv {
registry: LendingPoolAddressesProviderRegistry;
wethGateway: WETHGateway;
flashLiquidationAdapter: FlashLiquidationAdapter;
paraswapLiquiditySwapAdapter: ParaSwapLiquiditySwapAdapter;
}
let buidlerevmSnapshotId: string = '0x1';
@ -92,6 +95,7 @@ const testEnv: TestEnv = {
uniswapLiquiditySwapAdapter: {} as UniswapLiquiditySwapAdapter,
uniswapRepayAdapter: {} as UniswapRepayAdapter,
flashLiquidationAdapter: {} as FlashLiquidationAdapter,
paraswapLiquiditySwapAdapter: {} as ParaSwapLiquiditySwapAdapter,
registry: {} as LendingPoolAddressesProviderRegistry,
wethGateway: {} as WETHGateway,
} as TestEnv;
@ -158,6 +162,8 @@ export async function initializeMakeSuite() {
testEnv.uniswapLiquiditySwapAdapter = await getUniswapLiquiditySwapAdapter();
testEnv.uniswapRepayAdapter = await getUniswapRepayAdapter();
testEnv.flashLiquidationAdapter = await getFlashLiquidationAdapter();
testEnv.paraswapLiquiditySwapAdapter = await getParaSwapLiquiditySwapAdapter();
}
const setSnapshot = async () => {

File diff suppressed because it is too large Load Diff

View File

@ -198,7 +198,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
it('should revert if not valid addresses provider', async () => {
const { weth } = testEnv;
expect(
await expect(
deployFlashLiquidationAdapter([
mockUniswapRouter.address,
mockUniswapRouter.address,

View File

@ -50,7 +50,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
it('should revert if not valid addresses provider', async () => {
const { weth } = testEnv;
expect(
await expect(
deployUniswapLiquiditySwapAdapter([
mockUniswapRouter.address,
mockUniswapRouter.address,
@ -196,6 +196,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
.div(
new BigNumber(daiPrice.toString()).times(new BigNumber(10).pow(collateralDecimals))
)
.div(new BigNumber(10).pow(principalDecimals))
.toFixed(0)
);
@ -318,6 +319,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
.div(
new BigNumber(daiPrice.toString()).times(new BigNumber(10).pow(collateralDecimals))
)
.div(new BigNumber(10).pow(principalDecimals))
.toFixed(0)
);
@ -871,6 +873,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
.div(
new BigNumber(daiPrice.toString()).times(new BigNumber(10).pow(collateralDecimals))
)
.div(new BigNumber(10).pow(principalDecimals))
.toFixed(0)
);
@ -1493,6 +1496,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
.div(
new BigNumber(daiPrice.toString()).times(new BigNumber(10).pow(collateralDecimals))
)
.div(new BigNumber(10).pow(principalDecimals))
.toFixed(0)
);
@ -1601,6 +1605,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
.div(
new BigNumber(daiPrice.toString()).times(new BigNumber(10).pow(collateralDecimals))
)
.div(new BigNumber(10).pow(principalDecimals))
.toFixed(0)
);

View File

@ -87,7 +87,7 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => {
it('should revert if not valid addresses provider', async () => {
const { weth } = testEnv;
expect(
await expect(
deployUniswapRepayAdapter([
mockUniswapRouter.address,
mockUniswapRouter.address,