mirror of
https://github.com/Instadapp/aave-protocol-v2.git
synced 2024-07-29 21:47:30 +00:00
add base tests
This commit is contained in:
parent
721e73c36e
commit
212cf76f23
43
contracts/mocks/flashloan/MockSwapAdapter.sol
Normal file
43
contracts/mocks/flashloan/MockSwapAdapter.sol
Normal file
|
@ -0,0 +1,43 @@
|
|||
// SPDX-License-Identifier: agpl-3.0
|
||||
pragma solidity ^0.6.8;
|
||||
|
||||
import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
|
||||
|
||||
import {MintableERC20} from '../tokens/MintableERC20.sol';
|
||||
import {ILendingPoolAddressesProvider} from '../../interfaces/ILendingPoolAddressesProvider.sol';
|
||||
import {ISwapAdapter} from '../../interfaces/ISwapAdapter.sol';
|
||||
|
||||
contract MockSwapAdapter is ISwapAdapter {
|
||||
uint256 amountToReturn;
|
||||
ILendingPoolAddressesProvider public addressesProvider;
|
||||
|
||||
event Swapped(address fromAsset, address toAsset, uint256 fromAmount, uint256 receivedAmount);
|
||||
|
||||
constructor(ILendingPoolAddressesProvider provider) public {
|
||||
addressesProvider = provider;
|
||||
}
|
||||
|
||||
function setAmountToReturn(uint256 amount) public {
|
||||
amountToReturn = amount;
|
||||
}
|
||||
|
||||
function executeOperation(
|
||||
address assetToSwapFrom,
|
||||
address assetToSwapTo,
|
||||
uint256 amountToSwap,
|
||||
address fundsDestination,
|
||||
bytes calldata params
|
||||
) external override {
|
||||
params;
|
||||
IERC20(assetToSwapFrom).transfer(address(1), amountToSwap); // We don't want to keep funds here
|
||||
MintableERC20(assetToSwapTo).mint(amountToReturn);
|
||||
IERC20(assetToSwapTo).approve(fundsDestination, amountToReturn);
|
||||
|
||||
emit Swapped(assetToSwapFrom, assetToSwapTo, amountToSwap, amountToReturn);
|
||||
}
|
||||
|
||||
function burnAsset(IERC20 asset, uint256 amount) public {
|
||||
uint256 amountToBurn = (amount == type(uint256).max) ? asset.balanceOf(address(this)) : amount;
|
||||
asset.transfer(address(0), amountToBurn);
|
||||
}
|
||||
}
|
|
@ -174,7 +174,7 @@
|
|||
},
|
||||
"WalletBalanceProvider": {
|
||||
"buidlerevm": {
|
||||
"address": "0xBEF0d4b9c089a5883741fC14cbA352055f35DDA2",
|
||||
"address": "0xDf73fC454FA018051D4a1509e63D11530A59DE10",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
|
@ -414,7 +414,7 @@
|
|||
},
|
||||
"AaveProtocolTestHelpers": {
|
||||
"buidlerevm": {
|
||||
"address": "0xDf73fC454FA018051D4a1509e63D11530A59DE10"
|
||||
"address": "0x2cfcA5785261fbC88EFFDd46fCFc04c22525F9e4"
|
||||
},
|
||||
"localhost": {
|
||||
"address": "0xDf73fC454FA018051D4a1509e63D11530A59DE10"
|
||||
|
@ -489,5 +489,10 @@
|
|||
"address": "0xA8083d78B6ABC328b4d3B714F76F384eCC7147e1",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"MockSwapAdapter": {
|
||||
"buidlerevm": {
|
||||
"address": "0xBEF0d4b9c089a5883741fC14cbA352055f35DDA2"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -31,6 +31,7 @@ import BigNumber from 'bignumber.js';
|
|||
import {Ierc20Detailed} from '../types/Ierc20Detailed';
|
||||
import {StableDebtToken} from '../types/StableDebtToken';
|
||||
import {VariableDebtToken} from '../types/VariableDebtToken';
|
||||
import {MockSwapAdapter} from '../types/MockSwapAdapter';
|
||||
|
||||
export const registerContractInJsonDb = async (contractId: string, contractInstance: Contract) => {
|
||||
const currentNetwork = BRE.network.name;
|
||||
|
@ -212,6 +213,9 @@ export const deployMockFlashLoanReceiver = async (addressesProvider: tEthereumAd
|
|||
addressesProvider,
|
||||
]);
|
||||
|
||||
export const deployMockSwapAdapter = async (addressesProvider: tEthereumAddress) =>
|
||||
await deployContract<MockSwapAdapter>(eContractid.MockSwapAdapter, [addressesProvider]);
|
||||
|
||||
export const deployWalletBalancerProvider = async (addressesProvider: tEthereumAddress) =>
|
||||
await deployContract<WalletBalanceProvider>(eContractid.WalletBalanceProvider, [
|
||||
addressesProvider,
|
||||
|
@ -387,6 +391,14 @@ export const getMockFlashLoanReceiver = async (address?: tEthereumAddress) => {
|
|||
);
|
||||
};
|
||||
|
||||
export const getMockSwapAdapter = async (address?: tEthereumAddress) => {
|
||||
return await getContract<MockSwapAdapter>(
|
||||
eContractid.MockSwapAdapter,
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.MockSwapAdapter}.${BRE.network.name}`).value()).address
|
||||
);
|
||||
};
|
||||
|
||||
export const getLendingRateOracle = async (address?: tEthereumAddress) => {
|
||||
return await getContract<LendingRateOracle>(
|
||||
eContractid.LendingRateOracle,
|
||||
|
|
|
@ -41,6 +41,7 @@ export enum eContractid {
|
|||
IERC20Detailed = 'IERC20Detailed',
|
||||
StableDebtToken = 'StableDebtToken',
|
||||
VariableDebtToken = 'VariableDebtToken',
|
||||
MockSwapAdapter = 'MockSwapAdapter',
|
||||
}
|
||||
|
||||
export enum ProtocolErrors {
|
||||
|
@ -111,7 +112,7 @@ export enum ProtocolErrors {
|
|||
INVALID_REDIRECTION_ADDRESS = 'Invalid redirection address',
|
||||
INVALID_HF = 'Invalid health factor',
|
||||
TRANSFER_AMOUNT_EXCEEDS_BALANCE = 'ERC20: transfer amount exceeds balance',
|
||||
SAFEERC20_LOWLEVEL_CALL = 'SafeERC20: low-level call failed'
|
||||
SAFEERC20_LOWLEVEL_CALL = 'SafeERC20: low-level call failed',
|
||||
}
|
||||
|
||||
export type tEthereumAddress = string;
|
||||
|
|
|
@ -23,6 +23,7 @@ import {
|
|||
deployStableDebtToken,
|
||||
deployVariableDebtToken,
|
||||
deployGenericAToken,
|
||||
deployMockSwapAdapter,
|
||||
} from '../helpers/contracts-helpers';
|
||||
import {LendingPoolAddressesProvider} from '../types/LendingPoolAddressesProvider';
|
||||
import {ContractTransaction, Signer} from 'ethers';
|
||||
|
@ -503,6 +504,9 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => {
|
|||
const mockFlashLoanReceiver = await deployMockFlashLoanReceiver(addressesProvider.address);
|
||||
await insertContractAddressInDb(eContractid.MockFlashLoanReceiver, mockFlashLoanReceiver.address);
|
||||
|
||||
const mockMockSwapAdapter = await deployMockSwapAdapter(addressesProvider.address);
|
||||
await insertContractAddressInDb(eContractid.MockSwapAdapter, mockMockSwapAdapter.address);
|
||||
|
||||
await deployWalletBalancerProvider(addressesProvider.address);
|
||||
|
||||
const testHelpers = await deployAaveProtocolTestHelpers(addressesProvider.address);
|
||||
|
|
111
test/collateral-swap.spec.ts
Normal file
111
test/collateral-swap.spec.ts
Normal file
|
@ -0,0 +1,111 @@
|
|||
import {makeSuite, TestEnv} from './helpers/make-suite';
|
||||
import {MockSwapAdapter} from '../types/MockSwapAdapter';
|
||||
import {getMockSwapAdapter} from '../helpers/contracts-helpers';
|
||||
import {ProtocolErrors} from '../helpers/types';
|
||||
import {ethers} from 'ethers';
|
||||
import {APPROVAL_AMOUNT_LENDING_POOL} from '../helpers/constants';
|
||||
|
||||
const {expect} = require('chai');
|
||||
|
||||
makeSuite('LendingPool CollateralSwap function', (testEnv: TestEnv) => {
|
||||
let _mockSwapAdapter = {} as MockSwapAdapter;
|
||||
const {HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD} = ProtocolErrors;
|
||||
|
||||
before(async () => {
|
||||
_mockSwapAdapter = await getMockSwapAdapter();
|
||||
});
|
||||
|
||||
it('Deposits WETH into the reserve', async () => {
|
||||
const {pool, weth, users} = testEnv;
|
||||
const amountToDeposit = ethers.utils.parseEther('1');
|
||||
|
||||
for (const signer of [weth.signer, users[2].signer]) {
|
||||
const connectedWETH = weth.connect(signer);
|
||||
await connectedWETH.mint(amountToDeposit);
|
||||
await connectedWETH.approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL);
|
||||
await pool.connect(signer).deposit(weth.address, amountToDeposit, '0');
|
||||
}
|
||||
});
|
||||
it('User tries to swap more then he can', async () => {
|
||||
const {pool, weth, dai} = testEnv;
|
||||
await expect(
|
||||
pool.collateralSwap(
|
||||
_mockSwapAdapter.address,
|
||||
weth.address,
|
||||
dai.address,
|
||||
ethers.utils.parseEther('1.1'),
|
||||
'0x10'
|
||||
)
|
||||
).to.be.revertedWith('ERC20: burn amount exceeds balance');
|
||||
});
|
||||
|
||||
it('User tries to swap more then available on the reserve', async () => {
|
||||
const {pool, weth, dai, users, aEth} = testEnv;
|
||||
|
||||
await pool.borrow(weth.address, ethers.utils.parseEther('0.1'), 1, 0);
|
||||
await pool.connect(users[2].signer).withdraw(weth.address, ethers.utils.parseEther('1'));
|
||||
|
||||
await expect(
|
||||
pool.collateralSwap(
|
||||
_mockSwapAdapter.address,
|
||||
weth.address,
|
||||
dai.address,
|
||||
ethers.utils.parseEther('1'),
|
||||
'0x10'
|
||||
)
|
||||
).to.be.revertedWith('SafeMath: subtraction overflow');
|
||||
await weth.mint(ethers.utils.parseEther('0.1'));
|
||||
await pool.repay(
|
||||
weth.address,
|
||||
ethers.utils.parseEther('0.2'),
|
||||
1,
|
||||
await pool.signer.getAddress()
|
||||
);
|
||||
});
|
||||
|
||||
it('User tries to swap correct amount', async () => {
|
||||
const {pool, weth, dai, aEth, aDai} = testEnv;
|
||||
const userAddress = await pool.signer.getAddress();
|
||||
const amountToSwap = ethers.utils.parseEther('0.25');
|
||||
|
||||
const amountToReturn = ethers.utils.parseEther('0.5');
|
||||
await _mockSwapAdapter.setAmountToReturn(amountToReturn);
|
||||
|
||||
const reserveBalanceWETHBefore = await weth.balanceOf(aEth.address);
|
||||
const reserveBalanceDAIBefore = await dai.balanceOf(aDai.address);
|
||||
|
||||
const userATokenBalanceWETHBefore = await aEth.balanceOf(userAddress);
|
||||
const userATokenBalanceDAIBefore = await aDai.balanceOf(userAddress);
|
||||
|
||||
await pool.collateralSwap(
|
||||
_mockSwapAdapter.address,
|
||||
weth.address,
|
||||
dai.address,
|
||||
amountToSwap,
|
||||
'0x10'
|
||||
);
|
||||
const userATokenBalanceWETHAfter = await aEth.balanceOf(userAddress);
|
||||
const userATokenBalanceDAIAfter = await aDai.balanceOf(userAddress);
|
||||
|
||||
const reserveBalanceWETHAfter = await weth.balanceOf(aEth.address);
|
||||
const reserveBalanceDAIAfter = await dai.balanceOf(aDai.address);
|
||||
|
||||
expect(userATokenBalanceWETHAfter.toString()).to.be.equal(
|
||||
userATokenBalanceWETHBefore.sub(amountToSwap).toString(),
|
||||
'was burned incorrect amount of user funds'
|
||||
);
|
||||
expect(userATokenBalanceDAIAfter.toString()).to.be.equal(
|
||||
userATokenBalanceDAIBefore.add(amountToReturn).toString(),
|
||||
'was minted incorrect amount of user funds'
|
||||
);
|
||||
|
||||
expect(reserveBalanceWETHAfter.toString()).to.be.equal(
|
||||
reserveBalanceWETHBefore.sub(amountToSwap).toString(),
|
||||
'was sent incorrect amount if reserve funds'
|
||||
);
|
||||
expect(reserveBalanceDAIAfter.toString()).to.be.equal(
|
||||
reserveBalanceDAIBefore.add(amountToReturn).toString(),
|
||||
'was received incorrect amount if reserve funds'
|
||||
);
|
||||
});
|
||||
});
|
|
@ -1,3 +1,5 @@
|
|||
import BigNumber from 'bignumber.js';
|
||||
|
||||
import {TestEnv, makeSuite} from './helpers/make-suite';
|
||||
import {APPROVAL_AMOUNT_LENDING_POOL, oneRay} from '../helpers/constants';
|
||||
import {
|
||||
|
@ -8,7 +10,6 @@ import {
|
|||
import {ethers} from 'ethers';
|
||||
import {MockFlashLoanReceiver} from '../types/MockFlashLoanReceiver';
|
||||
import {ProtocolErrors, eContractid} from '../helpers/types';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import {VariableDebtToken} from '../types/VariableDebtToken';
|
||||
import {StableDebtToken} from '../types/StableDebtToken';
|
||||
|
||||
|
@ -21,14 +22,14 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
|||
REQUESTED_AMOUNT_TOO_SMALL,
|
||||
TRANSFER_AMOUNT_EXCEEDS_BALANCE,
|
||||
INVALID_FLASHLOAN_MODE,
|
||||
SAFEERC20_LOWLEVEL_CALL
|
||||
SAFEERC20_LOWLEVEL_CALL,
|
||||
} = ProtocolErrors;
|
||||
|
||||
before(async () => {
|
||||
_mockFlashLoanReceiver = await getMockFlashLoanReceiver();
|
||||
});
|
||||
|
||||
it('Deposits ETH into the reserve', async () => {
|
||||
it('Deposits WETH into the reserve', async () => {
|
||||
const {pool, weth} = testEnv;
|
||||
const amountToDeposit = ethers.utils.parseEther('1');
|
||||
|
||||
|
@ -340,8 +341,8 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
|||
await _mockFlashLoanReceiver.setFailExecutionTransfer(true);
|
||||
|
||||
await pool
|
||||
.connect(caller.signer)
|
||||
.flashLoan(_mockFlashLoanReceiver.address, weth.address, flashAmount, 1, '0x10', '0');
|
||||
.connect(caller.signer)
|
||||
.flashLoan(_mockFlashLoanReceiver.address, weth.address, flashAmount, 1, '0x10', '0');
|
||||
|
||||
const {stableDebtTokenAddress} = await pool.getReserveTokensAddresses(weth.address);
|
||||
|
||||
|
@ -353,6 +354,5 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
|||
const callerDebt = await wethDebtToken.balanceOf(caller.address);
|
||||
|
||||
expect(callerDebt.toString()).to.be.equal('800720000000000000', 'Invalid user debt');
|
||||
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue
Block a user