mirror of
https://github.com/Instadapp/aave-protocol-v2.git
synced 2024-07-29 21:47:30 +00:00
242826ded6
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.
2333 lines
87 KiB
TypeScript
2333 lines
87 KiB
TypeScript
import { makeSuite, TestEnv } from './helpers/make-suite';
|
|
import {
|
|
convertToCurrencyDecimals,
|
|
getContract,
|
|
buildPermitParams,
|
|
getSignatureFromTypedData,
|
|
buildParaSwapLiquiditySwapParams,
|
|
} from '../helpers/contracts-helpers';
|
|
import { getMockParaSwapAugustus } from '../helpers/contracts-getters';
|
|
import { deployParaSwapLiquiditySwapAdapter } from '../helpers/contracts-deployments';
|
|
import { MockParaSwapAugustus } from '../types/MockParaSwapAugustus';
|
|
import { Zero } from '@ethersproject/constants';
|
|
import BigNumber from 'bignumber.js';
|
|
import { DRE, evmRevert, evmSnapshot } from '../helpers/misc-utils';
|
|
import { ethers } from 'ethers';
|
|
import { eContractid } from '../helpers/types';
|
|
import { AToken } from '../types/AToken';
|
|
import { BUIDLEREVM_CHAINID } from '../helpers/buidler-constants';
|
|
import { MAX_UINT_AMOUNT } from '../helpers/constants';
|
|
const { parseEther } = ethers.utils;
|
|
|
|
const { expect } = require('chai');
|
|
|
|
makeSuite('ParaSwap adapters', (testEnv: TestEnv) => {
|
|
let mockAugustus: MockParaSwapAugustus;
|
|
let evmSnapshotId: string;
|
|
|
|
before(async () => {
|
|
mockAugustus = await getMockParaSwapAugustus();
|
|
});
|
|
|
|
beforeEach(async () => {
|
|
evmSnapshotId = await evmSnapshot();
|
|
});
|
|
|
|
afterEach(async () => {
|
|
await evmRevert(evmSnapshotId);
|
|
});
|
|
|
|
describe('ParaSwapLiquiditySwapAdapter', () => {
|
|
describe('constructor', () => {
|
|
it('should deploy with correct parameters', async () => {
|
|
const { addressesProvider } = testEnv;
|
|
await deployParaSwapLiquiditySwapAdapter([
|
|
addressesProvider.address,
|
|
]);
|
|
});
|
|
|
|
it('should revert if not valid addresses provider', async () => {
|
|
await expect(
|
|
deployParaSwapLiquiditySwapAdapter([
|
|
mockAugustus.address,
|
|
])
|
|
).to.be.reverted;
|
|
});
|
|
});
|
|
|
|
describe('executeOperation', () => {
|
|
beforeEach(async () => {
|
|
const { users, weth, dai, pool, deployer } = testEnv;
|
|
const userAddress = users[0].address;
|
|
|
|
// Provide liquidity
|
|
await dai.mint(parseEther('20000'));
|
|
await dai.approve(pool.address, parseEther('20000'));
|
|
await pool.deposit(dai.address, parseEther('20000'), deployer.address, 0);
|
|
|
|
await weth.mint(parseEther('10000'));
|
|
await weth.approve(pool.address, parseEther('10000'));
|
|
await pool.deposit(weth.address, parseEther('10000'), deployer.address, 0);
|
|
|
|
// Make a deposit for user
|
|
await weth.mint(parseEther('100'));
|
|
await weth.approve(pool.address, parseEther('100'));
|
|
await pool.deposit(weth.address, parseEther('100'), userAddress, 0);
|
|
});
|
|
|
|
it('should correctly swap tokens and deposit the out tokens in the pool', async () => {
|
|
const {
|
|
users,
|
|
weth,
|
|
oracle,
|
|
dai,
|
|
aDai,
|
|
aWETH,
|
|
pool,
|
|
paraswapLiquiditySwapAdapter,
|
|
} = testEnv;
|
|
const user = users[0].signer;
|
|
const userAddress = users[0].address;
|
|
|
|
const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
|
|
|
|
const daiPrice = await oracle.getAssetPrice(dai.address);
|
|
const expectedDaiAmount = await convertToCurrencyDecimals(
|
|
dai.address,
|
|
new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
|
|
);
|
|
|
|
await mockAugustus.expectSwap(weth.address, dai.address, amountWETHtoSwap, amountWETHtoSwap, expectedDaiAmount);
|
|
|
|
const flashloanPremium = amountWETHtoSwap.mul(9).div(10000);
|
|
const flashloanTotal = amountWETHtoSwap.add(flashloanPremium);
|
|
|
|
// User will swap liquidity aEth to aDai
|
|
const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
|
|
await aWETH.connect(user).approve(paraswapLiquiditySwapAdapter.address, flashloanTotal);
|
|
|
|
const mockAugustusCalldata = mockAugustus.interface.encodeFunctionData(
|
|
'swap',
|
|
[weth.address, dai.address, amountWETHtoSwap, expectedDaiAmount]
|
|
);
|
|
|
|
const params = buildParaSwapLiquiditySwapParams(
|
|
dai.address,
|
|
expectedDaiAmount,
|
|
0,
|
|
mockAugustusCalldata,
|
|
mockAugustus.address,
|
|
0,
|
|
0,
|
|
0,
|
|
'0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
'0x0000000000000000000000000000000000000000000000000000000000000000'
|
|
);
|
|
|
|
await expect(
|
|
pool
|
|
.connect(user)
|
|
.flashLoan(
|
|
paraswapLiquiditySwapAdapter.address,
|
|
[weth.address],
|
|
[amountWETHtoSwap],
|
|
[0],
|
|
userAddress,
|
|
params,
|
|
0
|
|
)
|
|
)
|
|
.to.emit(paraswapLiquiditySwapAdapter, 'Swapped')
|
|
.withArgs(weth.address, dai.address, amountWETHtoSwap, expectedDaiAmount);
|
|
|
|
const adapterWethBalance = await weth.balanceOf(paraswapLiquiditySwapAdapter.address);
|
|
const adapterDaiBalance = await dai.balanceOf(paraswapLiquiditySwapAdapter.address);
|
|
const userADaiBalance = await aDai.balanceOf(userAddress);
|
|
const userAEthBalance = await aWETH.balanceOf(userAddress);
|
|
|
|
// N.B. will get some portion of flashloan premium back from the pool
|
|
expect(adapterWethBalance).to.be.eq(Zero);
|
|
expect(adapterDaiBalance).to.be.eq(Zero);
|
|
expect(userADaiBalance).to.be.eq(expectedDaiAmount);
|
|
expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(flashloanTotal));
|
|
expect(userAEthBalance).to.be.lte(userAEthBalanceBefore.sub(amountWETHtoSwap));
|
|
});
|
|
|
|
it('should correctly swap tokens using permit', async () => {
|
|
const {
|
|
users,
|
|
weth,
|
|
oracle,
|
|
dai,
|
|
aDai,
|
|
aWETH,
|
|
pool,
|
|
paraswapLiquiditySwapAdapter,
|
|
} = testEnv;
|
|
const user = users[0].signer;
|
|
const userAddress = users[0].address;
|
|
|
|
const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
|
|
|
|
const daiPrice = await oracle.getAssetPrice(dai.address);
|
|
const expectedDaiAmount = await convertToCurrencyDecimals(
|
|
dai.address,
|
|
new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
|
|
);
|
|
|
|
await mockAugustus.expectSwap(weth.address, dai.address, amountWETHtoSwap, amountWETHtoSwap, expectedDaiAmount);
|
|
|
|
const flashloanPremium = amountWETHtoSwap.mul(9).div(10000);
|
|
const flashloanTotal = amountWETHtoSwap.add(flashloanPremium);
|
|
|
|
// User will swap liquidity aEth to aDai
|
|
const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
|
|
|
|
const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID;
|
|
const deadline = MAX_UINT_AMOUNT;
|
|
const nonce = (await aWETH._nonces(userAddress)).toNumber();
|
|
const msgParams = buildPermitParams(
|
|
chainId,
|
|
aWETH.address,
|
|
'1',
|
|
await aWETH.name(),
|
|
userAddress,
|
|
paraswapLiquiditySwapAdapter.address,
|
|
nonce,
|
|
deadline,
|
|
flashloanTotal.toString()
|
|
);
|
|
|
|
const ownerPrivateKey = require('../test-wallets.js').accounts[1].secretKey;
|
|
if (!ownerPrivateKey) {
|
|
throw new Error('INVALID_OWNER_PK');
|
|
}
|
|
|
|
const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams);
|
|
|
|
const mockAugustusCalldata = mockAugustus.interface.encodeFunctionData(
|
|
'swap',
|
|
[weth.address, dai.address, amountWETHtoSwap, expectedDaiAmount]
|
|
);
|
|
|
|
const params = buildParaSwapLiquiditySwapParams(
|
|
dai.address,
|
|
expectedDaiAmount,
|
|
0,
|
|
mockAugustusCalldata,
|
|
mockAugustus.address,
|
|
flashloanTotal,
|
|
deadline,
|
|
v,
|
|
r,
|
|
s
|
|
);
|
|
|
|
await expect(
|
|
pool
|
|
.connect(user)
|
|
.flashLoan(
|
|
paraswapLiquiditySwapAdapter.address,
|
|
[weth.address],
|
|
[amountWETHtoSwap],
|
|
[0],
|
|
userAddress,
|
|
params,
|
|
0
|
|
)
|
|
)
|
|
.to.emit(paraswapLiquiditySwapAdapter, 'Swapped')
|
|
.withArgs(weth.address, dai.address, amountWETHtoSwap, expectedDaiAmount);
|
|
|
|
const adapterWethBalance = await weth.balanceOf(paraswapLiquiditySwapAdapter.address);
|
|
const adapterDaiBalance = await dai.balanceOf(paraswapLiquiditySwapAdapter.address);
|
|
const userADaiBalance = await aDai.balanceOf(userAddress);
|
|
const userAEthBalance = await aWETH.balanceOf(userAddress);
|
|
|
|
// N.B. will get some portion of flashloan premium back from the pool
|
|
expect(adapterWethBalance).to.be.eq(Zero);
|
|
expect(adapterDaiBalance).to.be.eq(Zero);
|
|
expect(userADaiBalance).to.be.eq(expectedDaiAmount);
|
|
expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(flashloanTotal));
|
|
expect(userAEthBalance).to.be.lte(userAEthBalanceBefore.sub(amountWETHtoSwap));
|
|
});
|
|
|
|
it('should revert if caller not lending pool', async () => {
|
|
const {
|
|
users,
|
|
weth,
|
|
oracle,
|
|
dai,
|
|
aWETH,
|
|
paraswapLiquiditySwapAdapter,
|
|
} = testEnv;
|
|
const user = users[0].signer;
|
|
const userAddress = users[0].address;
|
|
|
|
const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
|
|
|
|
const daiPrice = await oracle.getAssetPrice(dai.address);
|
|
const expectedDaiAmount = await convertToCurrencyDecimals(
|
|
dai.address,
|
|
new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
|
|
);
|
|
|
|
await mockAugustus.expectSwap(weth.address, dai.address, amountWETHtoSwap, amountWETHtoSwap, expectedDaiAmount);
|
|
|
|
const flashloanPremium = amountWETHtoSwap.mul(9).div(10000);
|
|
const flashloanTotal = amountWETHtoSwap.add(flashloanPremium);
|
|
|
|
// User will swap liquidity aEth to aDai
|
|
await aWETH.connect(user).approve(paraswapLiquiditySwapAdapter.address, flashloanTotal);
|
|
|
|
const mockAugustusCalldata = mockAugustus.interface.encodeFunctionData(
|
|
'swap',
|
|
[weth.address, dai.address, amountWETHtoSwap, expectedDaiAmount]
|
|
);
|
|
|
|
const params = buildParaSwapLiquiditySwapParams(
|
|
dai.address,
|
|
expectedDaiAmount,
|
|
0,
|
|
mockAugustusCalldata,
|
|
mockAugustus.address,
|
|
0,
|
|
0,
|
|
0,
|
|
'0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
'0x0000000000000000000000000000000000000000000000000000000000000000'
|
|
);
|
|
|
|
await expect(
|
|
paraswapLiquiditySwapAdapter
|
|
.connect(user)
|
|
.executeOperation(
|
|
[weth.address],
|
|
[amountWETHtoSwap],
|
|
[0],
|
|
userAddress,
|
|
params
|
|
)
|
|
).to.be.revertedWith('CALLER_MUST_BE_LENDING_POOL');
|
|
});
|
|
|
|
it('should work correctly with tokens of different decimals', async () => {
|
|
const {
|
|
users,
|
|
usdc,
|
|
oracle,
|
|
dai,
|
|
aDai,
|
|
paraswapLiquiditySwapAdapter,
|
|
pool,
|
|
deployer,
|
|
} = testEnv;
|
|
const user = users[0].signer;
|
|
const userAddress = users[0].address;
|
|
|
|
const amountUSDCtoSwap = await convertToCurrencyDecimals(usdc.address, '10');
|
|
const liquidity = await convertToCurrencyDecimals(usdc.address, '20000');
|
|
|
|
const flashloanPremium = amountUSDCtoSwap.mul(9).div(10000);
|
|
const flashloanTotal = amountUSDCtoSwap.add(flashloanPremium);
|
|
|
|
// Provider liquidity
|
|
await usdc.mint(liquidity);
|
|
await usdc.approve(pool.address, liquidity);
|
|
await pool.deposit(usdc.address, liquidity, deployer.address, 0);
|
|
|
|
// Make a deposit for user
|
|
await usdc.connect(user).mint(flashloanTotal);
|
|
await usdc.connect(user).approve(pool.address, flashloanTotal);
|
|
await pool.connect(user).deposit(usdc.address, flashloanTotal, userAddress, 0);
|
|
|
|
const usdcPrice = await oracle.getAssetPrice(usdc.address);
|
|
const daiPrice = await oracle.getAssetPrice(dai.address);
|
|
|
|
const collateralDecimals = (await usdc.decimals()).toString();
|
|
const principalDecimals = (await dai.decimals()).toString();
|
|
|
|
const expectedDaiAmount = await convertToCurrencyDecimals(
|
|
dai.address,
|
|
new BigNumber(amountUSDCtoSwap.toString())
|
|
.times(
|
|
new BigNumber(usdcPrice.toString()).times(new BigNumber(10).pow(principalDecimals))
|
|
)
|
|
.div(
|
|
new BigNumber(daiPrice.toString()).times(new BigNumber(10).pow(collateralDecimals))
|
|
)
|
|
.div(new BigNumber(10).pow(principalDecimals))
|
|
.toFixed(0)
|
|
);
|
|
|
|
await mockAugustus.expectSwap(usdc.address, dai.address, amountUSDCtoSwap, amountUSDCtoSwap, expectedDaiAmount);
|
|
|
|
const aUsdcData = await pool.getReserveData(usdc.address);
|
|
const aUsdc = await getContract<AToken>(eContractid.AToken, aUsdcData.aTokenAddress);
|
|
|
|
// User will swap liquidity aUsdc to aDai
|
|
const userAUsdcBalanceBefore = await aUsdc.balanceOf(userAddress);
|
|
await aUsdc.connect(user).approve(paraswapLiquiditySwapAdapter.address, flashloanTotal);
|
|
|
|
const mockAugustusCalldata = mockAugustus.interface.encodeFunctionData(
|
|
'swap',
|
|
[usdc.address, dai.address, amountUSDCtoSwap, expectedDaiAmount]
|
|
);
|
|
|
|
const params = buildParaSwapLiquiditySwapParams(
|
|
dai.address,
|
|
expectedDaiAmount,
|
|
0,
|
|
mockAugustusCalldata,
|
|
mockAugustus.address,
|
|
0,
|
|
0,
|
|
0,
|
|
'0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
'0x0000000000000000000000000000000000000000000000000000000000000000'
|
|
);
|
|
|
|
await expect(
|
|
pool
|
|
.connect(user)
|
|
.flashLoan(
|
|
paraswapLiquiditySwapAdapter.address,
|
|
[usdc.address],
|
|
[amountUSDCtoSwap],
|
|
[0],
|
|
userAddress,
|
|
params,
|
|
0
|
|
)
|
|
)
|
|
.to.emit(paraswapLiquiditySwapAdapter, 'Swapped')
|
|
.withArgs(usdc.address, dai.address, amountUSDCtoSwap, expectedDaiAmount);
|
|
|
|
const adapterUsdcBalance = await usdc.balanceOf(paraswapLiquiditySwapAdapter.address);
|
|
const adapterDaiBalance = await dai.balanceOf(paraswapLiquiditySwapAdapter.address);
|
|
const userADaiBalance = await aDai.balanceOf(userAddress);
|
|
const userAUsdcBalance = await aUsdc.balanceOf(userAddress);
|
|
|
|
// N.B. will get some portion of flashloan premium back from the pool
|
|
expect(adapterUsdcBalance).to.be.eq(Zero);
|
|
expect(adapterDaiBalance).to.be.eq(Zero);
|
|
expect(userADaiBalance).to.be.eq(expectedDaiAmount);
|
|
expect(userAUsdcBalance).to.be.gte(userAUsdcBalanceBefore.sub(flashloanTotal));
|
|
expect(userAUsdcBalance).to.be.lte(userAUsdcBalanceBefore.sub(amountUSDCtoSwap));
|
|
});
|
|
|
|
it('should revert when min amount to receive exceeds the max slippage amount', async () => {
|
|
const {
|
|
users,
|
|
weth,
|
|
oracle,
|
|
dai,
|
|
aWETH,
|
|
pool,
|
|
paraswapLiquiditySwapAdapter,
|
|
} = testEnv;
|
|
const user = users[0].signer;
|
|
const userAddress = users[0].address;
|
|
|
|
const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
|
|
|
|
const daiPrice = await oracle.getAssetPrice(dai.address);
|
|
const expectedDaiAmount = await convertToCurrencyDecimals(
|
|
dai.address,
|
|
new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
|
|
);
|
|
|
|
await mockAugustus.expectSwap(weth.address, dai.address, amountWETHtoSwap, amountWETHtoSwap, expectedDaiAmount);
|
|
|
|
const smallExpectedDaiAmount = expectedDaiAmount.div(2);
|
|
|
|
const flashloanPremium = amountWETHtoSwap.mul(9).div(10000);
|
|
const flashloanTotal = amountWETHtoSwap.add(flashloanPremium);
|
|
|
|
// User will swap liquidity aEth to aDai
|
|
await aWETH.connect(user).approve(paraswapLiquiditySwapAdapter.address, flashloanTotal);
|
|
|
|
const mockAugustusCalldata = mockAugustus.interface.encodeFunctionData(
|
|
'swap',
|
|
[weth.address, dai.address, amountWETHtoSwap, expectedDaiAmount]
|
|
);
|
|
|
|
const params = buildParaSwapLiquiditySwapParams(
|
|
dai.address,
|
|
smallExpectedDaiAmount,
|
|
0,
|
|
mockAugustusCalldata,
|
|
mockAugustus.address,
|
|
0,
|
|
0,
|
|
0,
|
|
'0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
'0x0000000000000000000000000000000000000000000000000000000000000000'
|
|
);
|
|
|
|
await expect(
|
|
pool
|
|
.connect(user)
|
|
.flashLoan(
|
|
paraswapLiquiditySwapAdapter.address,
|
|
[weth.address],
|
|
[amountWETHtoSwap],
|
|
[0],
|
|
userAddress,
|
|
params,
|
|
0
|
|
)
|
|
).to.be.revertedWith('MIN_AMOUNT_EXCEEDS_MAX_SLIPPAGE');
|
|
});
|
|
|
|
it('should revert when min amount to receive exceeds the max slippage amount (with tokens of different decimals)', async () => {
|
|
const {
|
|
users,
|
|
usdc,
|
|
oracle,
|
|
dai,
|
|
paraswapLiquiditySwapAdapter,
|
|
pool,
|
|
deployer,
|
|
} = testEnv;
|
|
const user = users[0].signer;
|
|
const userAddress = users[0].address;
|
|
|
|
const amountUSDCtoSwap = await convertToCurrencyDecimals(usdc.address, '10');
|
|
const liquidity = await convertToCurrencyDecimals(usdc.address, '20000');
|
|
|
|
const flashloanPremium = amountUSDCtoSwap.mul(9).div(10000);
|
|
const flashloanTotal = amountUSDCtoSwap.add(flashloanPremium);
|
|
|
|
// Provider liquidity
|
|
await usdc.mint(liquidity);
|
|
await usdc.approve(pool.address, liquidity);
|
|
await pool.deposit(usdc.address, liquidity, deployer.address, 0);
|
|
|
|
// Make a deposit for user
|
|
await usdc.connect(user).mint(flashloanTotal);
|
|
await usdc.connect(user).approve(pool.address, flashloanTotal);
|
|
await pool.connect(user).deposit(usdc.address, flashloanTotal, userAddress, 0);
|
|
|
|
const usdcPrice = await oracle.getAssetPrice(usdc.address);
|
|
const daiPrice = await oracle.getAssetPrice(dai.address);
|
|
|
|
const collateralDecimals = (await usdc.decimals()).toString();
|
|
const principalDecimals = (await dai.decimals()).toString();
|
|
|
|
const expectedDaiAmount = await convertToCurrencyDecimals(
|
|
dai.address,
|
|
new BigNumber(amountUSDCtoSwap.toString())
|
|
.times(
|
|
new BigNumber(usdcPrice.toString()).times(new BigNumber(10).pow(principalDecimals))
|
|
)
|
|
.div(
|
|
new BigNumber(daiPrice.toString()).times(new BigNumber(10).pow(collateralDecimals))
|
|
)
|
|
.div(new BigNumber(10).pow(principalDecimals))
|
|
.toFixed(0)
|
|
);
|
|
|
|
await mockAugustus.expectSwap(usdc.address, dai.address, amountUSDCtoSwap, amountUSDCtoSwap, expectedDaiAmount);
|
|
|
|
const smallExpectedDaiAmount = expectedDaiAmount.div(2);
|
|
|
|
const aUsdcData = await pool.getReserveData(usdc.address);
|
|
const aUsdc = await getContract<AToken>(eContractid.AToken, aUsdcData.aTokenAddress);
|
|
|
|
// User will swap liquidity aUsdc to aDai
|
|
await aUsdc.connect(user).approve(paraswapLiquiditySwapAdapter.address, flashloanTotal);
|
|
|
|
const mockAugustusCalldata = mockAugustus.interface.encodeFunctionData(
|
|
'swap',
|
|
[usdc.address, dai.address, amountUSDCtoSwap, expectedDaiAmount]
|
|
);
|
|
|
|
const params = buildParaSwapLiquiditySwapParams(
|
|
dai.address,
|
|
smallExpectedDaiAmount,
|
|
0,
|
|
mockAugustusCalldata,
|
|
mockAugustus.address,
|
|
0,
|
|
0,
|
|
0,
|
|
'0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
'0x0000000000000000000000000000000000000000000000000000000000000000'
|
|
);
|
|
|
|
await expect(
|
|
pool
|
|
.connect(user)
|
|
.flashLoan(
|
|
paraswapLiquiditySwapAdapter.address,
|
|
[usdc.address],
|
|
[amountUSDCtoSwap],
|
|
[0],
|
|
userAddress,
|
|
params,
|
|
0
|
|
)
|
|
).to.be.revertedWith('MIN_AMOUNT_EXCEEDS_MAX_SLIPPAGE');
|
|
});
|
|
|
|
it('should correctly swap tokens all the balance', async () => {
|
|
const {
|
|
users,
|
|
weth,
|
|
oracle,
|
|
dai,
|
|
aDai,
|
|
aWETH,
|
|
pool,
|
|
paraswapLiquiditySwapAdapter,
|
|
} = testEnv;
|
|
const user = users[0].signer;
|
|
const userAddress = users[0].address;
|
|
|
|
const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
|
|
|
|
const daiPrice = await oracle.getAssetPrice(dai.address);
|
|
const expectedDaiAmount = await convertToCurrencyDecimals(
|
|
dai.address,
|
|
new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
|
|
);
|
|
|
|
await mockAugustus.expectSwap(weth.address, dai.address, amountWETHtoSwap, amountWETHtoSwap, expectedDaiAmount);
|
|
|
|
const bigAmountToSwap = parseEther('11');
|
|
const flashloanPremium = bigAmountToSwap.mul(9).div(10000);
|
|
const flashloanTotal = bigAmountToSwap.add(flashloanPremium);
|
|
|
|
// Remove other balance
|
|
await aWETH.connect(user).transfer(users[1].address, parseEther('90').sub(flashloanPremium));
|
|
|
|
// User will swap liquidity aEth to aDai
|
|
const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
|
|
expect(userAEthBalanceBefore).to.be.eq(amountWETHtoSwap.add(flashloanPremium));
|
|
|
|
await aWETH.connect(user).approve(paraswapLiquiditySwapAdapter.address, flashloanTotal);
|
|
|
|
const mockAugustusCalldata = mockAugustus.interface.encodeFunctionData(
|
|
'swap',
|
|
[weth.address, dai.address, bigAmountToSwap, expectedDaiAmount]
|
|
);
|
|
|
|
const params = buildParaSwapLiquiditySwapParams(
|
|
dai.address,
|
|
expectedDaiAmount,
|
|
4 + 2*32,
|
|
mockAugustusCalldata,
|
|
mockAugustus.address,
|
|
0,
|
|
0,
|
|
0,
|
|
'0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
'0x0000000000000000000000000000000000000000000000000000000000000000'
|
|
);
|
|
|
|
await expect(
|
|
pool
|
|
.connect(user)
|
|
.flashLoan(
|
|
paraswapLiquiditySwapAdapter.address,
|
|
[weth.address],
|
|
[bigAmountToSwap],
|
|
[0],
|
|
userAddress,
|
|
params,
|
|
0
|
|
)
|
|
)
|
|
.to.emit(paraswapLiquiditySwapAdapter, 'Swapped')
|
|
.withArgs(weth.address, dai.address, amountWETHtoSwap, expectedDaiAmount);
|
|
|
|
const adapterWethBalance = await weth.balanceOf(paraswapLiquiditySwapAdapter.address);
|
|
const adapterDaiBalance = await dai.balanceOf(paraswapLiquiditySwapAdapter.address);
|
|
const userADaiBalance = await aDai.balanceOf(userAddress);
|
|
const userAEthBalance = await aWETH.balanceOf(userAddress);
|
|
|
|
expect(adapterWethBalance).to.be.eq(Zero);
|
|
expect(adapterDaiBalance).to.be.eq(Zero);
|
|
expect(userADaiBalance).to.be.eq(expectedDaiAmount);
|
|
expect(userAEthBalance).to.be.eq(Zero);
|
|
});
|
|
|
|
it('should correctly swap tokens all the balance using permit', async () => {
|
|
const {
|
|
users,
|
|
weth,
|
|
oracle,
|
|
dai,
|
|
aDai,
|
|
aWETH,
|
|
pool,
|
|
paraswapLiquiditySwapAdapter,
|
|
} = testEnv;
|
|
const user = users[0].signer;
|
|
const userAddress = users[0].address;
|
|
|
|
const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
|
|
|
|
const daiPrice = await oracle.getAssetPrice(dai.address);
|
|
const expectedDaiAmount = await convertToCurrencyDecimals(
|
|
dai.address,
|
|
new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
|
|
);
|
|
|
|
await mockAugustus.expectSwap(weth.address, dai.address, amountWETHtoSwap, amountWETHtoSwap, expectedDaiAmount);
|
|
|
|
const bigAmountToSwap = parseEther('11');
|
|
const flashloanPremium = bigAmountToSwap.mul(9).div(10000);
|
|
const flashloanTotal = bigAmountToSwap.add(flashloanPremium);
|
|
|
|
// Remove other balance
|
|
await aWETH.connect(user).transfer(users[1].address, parseEther('90').sub(flashloanPremium));
|
|
|
|
// User will swap liquidity aEth to aDai
|
|
const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
|
|
expect(userAEthBalanceBefore).to.be.eq(amountWETHtoSwap.add(flashloanPremium));
|
|
|
|
const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID;
|
|
const deadline = MAX_UINT_AMOUNT;
|
|
const nonce = (await aWETH._nonces(userAddress)).toNumber();
|
|
const msgParams = buildPermitParams(
|
|
chainId,
|
|
aWETH.address,
|
|
'1',
|
|
await aWETH.name(),
|
|
userAddress,
|
|
paraswapLiquiditySwapAdapter.address,
|
|
nonce,
|
|
deadline,
|
|
flashloanTotal.toString()
|
|
);
|
|
|
|
const ownerPrivateKey = require('../test-wallets.js').accounts[1].secretKey;
|
|
if (!ownerPrivateKey) {
|
|
throw new Error('INVALID_OWNER_PK');
|
|
}
|
|
|
|
const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams);
|
|
|
|
const mockAugustusCalldata = mockAugustus.interface.encodeFunctionData(
|
|
'swap',
|
|
[weth.address, dai.address, bigAmountToSwap, expectedDaiAmount]
|
|
);
|
|
|
|
const params = buildParaSwapLiquiditySwapParams(
|
|
dai.address,
|
|
expectedDaiAmount,
|
|
4 + 2*32,
|
|
mockAugustusCalldata,
|
|
mockAugustus.address,
|
|
flashloanTotal,
|
|
deadline,
|
|
v,
|
|
r,
|
|
s
|
|
);
|
|
|
|
await expect(
|
|
pool
|
|
.connect(user)
|
|
.flashLoan(
|
|
paraswapLiquiditySwapAdapter.address,
|
|
[weth.address],
|
|
[bigAmountToSwap],
|
|
[0],
|
|
userAddress,
|
|
params,
|
|
0
|
|
)
|
|
)
|
|
.to.emit(paraswapLiquiditySwapAdapter, 'Swapped')
|
|
.withArgs(weth.address, dai.address, amountWETHtoSwap, expectedDaiAmount);
|
|
|
|
const adapterWethBalance = await weth.balanceOf(paraswapLiquiditySwapAdapter.address);
|
|
const adapterDaiBalance = await dai.balanceOf(paraswapLiquiditySwapAdapter.address);
|
|
const userADaiBalance = await aDai.balanceOf(userAddress);
|
|
const userAEthBalance = await aWETH.balanceOf(userAddress);
|
|
|
|
expect(adapterWethBalance).to.be.eq(Zero);
|
|
expect(adapterDaiBalance).to.be.eq(Zero);
|
|
expect(userADaiBalance).to.be.eq(expectedDaiAmount);
|
|
expect(userAEthBalance).to.be.eq(Zero);
|
|
});
|
|
|
|
it('should revert trying to swap all the balance with insufficient amount', async () => {
|
|
const {
|
|
users,
|
|
weth,
|
|
oracle,
|
|
dai,
|
|
aWETH,
|
|
pool,
|
|
paraswapLiquiditySwapAdapter,
|
|
} = testEnv;
|
|
const user = users[0].signer;
|
|
const userAddress = users[0].address;
|
|
|
|
const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
|
|
|
|
const daiPrice = await oracle.getAssetPrice(dai.address);
|
|
const expectedDaiAmount = await convertToCurrencyDecimals(
|
|
dai.address,
|
|
new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
|
|
);
|
|
|
|
await mockAugustus.expectSwap(weth.address, dai.address, amountWETHtoSwap, amountWETHtoSwap, expectedDaiAmount);
|
|
|
|
const smallAmountToSwap = parseEther('9');
|
|
const flashloanPremium = smallAmountToSwap.mul(9).div(10000);
|
|
const flashloanTotal = smallAmountToSwap.add(flashloanPremium);
|
|
|
|
// Remove other balance
|
|
await aWETH.connect(user).transfer(users[1].address, parseEther('90').sub(flashloanPremium));
|
|
|
|
// User will swap liquidity aEth to aDai
|
|
const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
|
|
expect(userAEthBalanceBefore).to.be.eq(amountWETHtoSwap.add(flashloanPremium));
|
|
|
|
await aWETH.connect(user).approve(paraswapLiquiditySwapAdapter.address, flashloanTotal);
|
|
|
|
const mockAugustusCalldata = mockAugustus.interface.encodeFunctionData(
|
|
'swap',
|
|
[weth.address, dai.address, smallAmountToSwap, expectedDaiAmount]
|
|
);
|
|
|
|
const params = buildParaSwapLiquiditySwapParams(
|
|
dai.address,
|
|
expectedDaiAmount,
|
|
4 + 2*32,
|
|
mockAugustusCalldata,
|
|
mockAugustus.address,
|
|
0,
|
|
0,
|
|
0,
|
|
'0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
'0x0000000000000000000000000000000000000000000000000000000000000000'
|
|
);
|
|
|
|
await expect(
|
|
pool
|
|
.connect(user)
|
|
.flashLoan(
|
|
paraswapLiquiditySwapAdapter.address,
|
|
[weth.address],
|
|
[smallAmountToSwap],
|
|
[0],
|
|
userAddress,
|
|
params,
|
|
0
|
|
)
|
|
).to.be.revertedWith('INSUFFICIENT_AMOUNT_TO_SWAP');
|
|
});
|
|
|
|
it('should revert trying to swap more than balance', async () => {
|
|
const {
|
|
users,
|
|
weth,
|
|
oracle,
|
|
dai,
|
|
aWETH,
|
|
pool,
|
|
paraswapLiquiditySwapAdapter,
|
|
} = testEnv;
|
|
const user = users[0].signer;
|
|
const userAddress = users[0].address;
|
|
|
|
const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '101');
|
|
|
|
const daiPrice = await oracle.getAssetPrice(dai.address);
|
|
const expectedDaiAmount = await convertToCurrencyDecimals(
|
|
dai.address,
|
|
new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
|
|
);
|
|
|
|
await mockAugustus.expectSwap(weth.address, dai.address, amountWETHtoSwap, amountWETHtoSwap, expectedDaiAmount);
|
|
|
|
const flashloanPremium = amountWETHtoSwap.mul(9).div(10000);
|
|
const flashloanTotal = amountWETHtoSwap.add(flashloanPremium);
|
|
|
|
// User will swap liquidity aEth to aDai
|
|
await aWETH.connect(user).approve(paraswapLiquiditySwapAdapter.address, flashloanTotal);
|
|
|
|
const mockAugustusCalldata = mockAugustus.interface.encodeFunctionData(
|
|
'swap',
|
|
[weth.address, dai.address, amountWETHtoSwap, expectedDaiAmount]
|
|
);
|
|
|
|
const params = buildParaSwapLiquiditySwapParams(
|
|
dai.address,
|
|
expectedDaiAmount,
|
|
0,
|
|
mockAugustusCalldata,
|
|
mockAugustus.address,
|
|
0,
|
|
0,
|
|
0,
|
|
'0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
'0x0000000000000000000000000000000000000000000000000000000000000000'
|
|
);
|
|
|
|
await expect(
|
|
pool
|
|
.connect(user)
|
|
.flashLoan(
|
|
paraswapLiquiditySwapAdapter.address,
|
|
[weth.address],
|
|
[amountWETHtoSwap],
|
|
[0],
|
|
userAddress,
|
|
params,
|
|
0
|
|
)
|
|
).to.be.revertedWith('INSUFFICIENT_ATOKEN_BALANCE');
|
|
});
|
|
|
|
it('should not touch any token balance already in the adapter', async () => {
|
|
const {
|
|
users,
|
|
weth,
|
|
oracle,
|
|
dai,
|
|
aDai,
|
|
aWETH,
|
|
pool,
|
|
paraswapLiquiditySwapAdapter,
|
|
} = testEnv;
|
|
const user = users[0].signer;
|
|
const userAddress = users[0].address;
|
|
|
|
// Put token balances in the adapter
|
|
const adapterWethBalanceBefore = parseEther('123');
|
|
await weth.mint(adapterWethBalanceBefore);
|
|
await weth.transfer(paraswapLiquiditySwapAdapter.address, adapterWethBalanceBefore);
|
|
const adapterDaiBalanceBefore = parseEther('234');
|
|
await dai.mint(adapterDaiBalanceBefore);
|
|
await dai.transfer(paraswapLiquiditySwapAdapter.address, adapterDaiBalanceBefore);
|
|
|
|
const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
|
|
|
|
const daiPrice = await oracle.getAssetPrice(dai.address);
|
|
const expectedDaiAmount = await convertToCurrencyDecimals(
|
|
dai.address,
|
|
new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
|
|
);
|
|
|
|
await mockAugustus.expectSwap(weth.address, dai.address, amountWETHtoSwap, amountWETHtoSwap, expectedDaiAmount);
|
|
|
|
const flashloanPremium = amountWETHtoSwap.mul(9).div(10000);
|
|
const flashloanTotal = amountWETHtoSwap.add(flashloanPremium);
|
|
|
|
// User will swap liquidity aEth to aDai
|
|
const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
|
|
await aWETH.connect(user).approve(paraswapLiquiditySwapAdapter.address, flashloanTotal);
|
|
|
|
const mockAugustusCalldata = mockAugustus.interface.encodeFunctionData(
|
|
'swap',
|
|
[weth.address, dai.address, amountWETHtoSwap, expectedDaiAmount]
|
|
);
|
|
|
|
const params = buildParaSwapLiquiditySwapParams(
|
|
dai.address,
|
|
expectedDaiAmount,
|
|
0,
|
|
mockAugustusCalldata,
|
|
mockAugustus.address,
|
|
0,
|
|
0,
|
|
0,
|
|
'0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
'0x0000000000000000000000000000000000000000000000000000000000000000'
|
|
);
|
|
|
|
await expect(
|
|
pool
|
|
.connect(user)
|
|
.flashLoan(
|
|
paraswapLiquiditySwapAdapter.address,
|
|
[weth.address],
|
|
[amountWETHtoSwap],
|
|
[0],
|
|
userAddress,
|
|
params,
|
|
0
|
|
)
|
|
)
|
|
.to.emit(paraswapLiquiditySwapAdapter, 'Swapped')
|
|
.withArgs(weth.address, dai.address, amountWETHtoSwap, expectedDaiAmount);
|
|
|
|
const adapterWethBalance = await weth.balanceOf(paraswapLiquiditySwapAdapter.address);
|
|
const adapterDaiBalance = await dai.balanceOf(paraswapLiquiditySwapAdapter.address);
|
|
const userADaiBalance = await aDai.balanceOf(userAddress);
|
|
const userAEthBalance = await aWETH.balanceOf(userAddress);
|
|
|
|
// N.B. will get some portion of flashloan premium back from the pool
|
|
expect(adapterWethBalance).to.be.eq(adapterWethBalanceBefore);
|
|
expect(adapterDaiBalance).to.be.eq(adapterDaiBalanceBefore);
|
|
expect(userADaiBalance).to.be.eq(expectedDaiAmount);
|
|
expect(userAEthBalance).to.be.gte(userAEthBalanceBefore.sub(flashloanTotal));
|
|
expect(userAEthBalance).to.be.lte(userAEthBalanceBefore.sub(amountWETHtoSwap));
|
|
});
|
|
});
|
|
|
|
describe('executeOperation with borrowing', () => {
|
|
beforeEach(async () => {
|
|
const { users, weth, dai, pool, deployer } = testEnv;
|
|
const userAddress = users[0].address;
|
|
const borrower = users[1].signer;
|
|
const borrowerAddress = users[1].address;
|
|
|
|
// Provide liquidity
|
|
await dai.mint(parseEther('20000'));
|
|
await dai.approve(pool.address, parseEther('20000'));
|
|
await pool.deposit(dai.address, parseEther('20000'), deployer.address, 0);
|
|
|
|
await weth.mint(parseEther('10000'));
|
|
await weth.approve(pool.address, parseEther('10000'));
|
|
await pool.deposit(weth.address, parseEther('10000'), deployer.address, 0);
|
|
|
|
// Make a deposit for user
|
|
await weth.mint(parseEther('100'));
|
|
await weth.approve(pool.address, parseEther('100'));
|
|
await pool.deposit(weth.address, parseEther('100'), userAddress, 0);
|
|
|
|
// Add borrowing
|
|
const collateralAmount = parseEther('10000000');
|
|
await dai.mint(collateralAmount);
|
|
await dai.approve(pool.address, collateralAmount);
|
|
await pool.deposit(dai.address, collateralAmount, borrowerAddress, 0);
|
|
await pool.connect(borrower).borrow(weth.address, parseEther('5000'), 2, 0, borrowerAddress);
|
|
});
|
|
|
|
it('should correctly swap tokens and deposit the out tokens in the pool', async () => {
|
|
const {
|
|
users,
|
|
weth,
|
|
oracle,
|
|
dai,
|
|
aDai,
|
|
aWETH,
|
|
pool,
|
|
paraswapLiquiditySwapAdapter,
|
|
} = testEnv;
|
|
const user = users[0].signer;
|
|
const userAddress = users[0].address;
|
|
|
|
const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
|
|
|
|
const daiPrice = await oracle.getAssetPrice(dai.address);
|
|
const expectedDaiAmount = await convertToCurrencyDecimals(
|
|
dai.address,
|
|
new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
|
|
);
|
|
|
|
await mockAugustus.expectSwap(weth.address, dai.address, amountWETHtoSwap, amountWETHtoSwap, expectedDaiAmount);
|
|
|
|
const flashloanPremium = amountWETHtoSwap.mul(9).div(10000);
|
|
const flashloanTotal = amountWETHtoSwap.add(flashloanPremium);
|
|
|
|
// User will swap liquidity aEth to aDai
|
|
const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
|
|
await aWETH.connect(user).approve(paraswapLiquiditySwapAdapter.address, flashloanTotal);
|
|
|
|
const mockAugustusCalldata = mockAugustus.interface.encodeFunctionData(
|
|
'swap',
|
|
[weth.address, dai.address, amountWETHtoSwap, expectedDaiAmount]
|
|
);
|
|
|
|
const params = buildParaSwapLiquiditySwapParams(
|
|
dai.address,
|
|
expectedDaiAmount,
|
|
0,
|
|
mockAugustusCalldata,
|
|
mockAugustus.address,
|
|
0,
|
|
0,
|
|
0,
|
|
'0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
'0x0000000000000000000000000000000000000000000000000000000000000000'
|
|
);
|
|
|
|
await expect(
|
|
pool
|
|
.connect(user)
|
|
.flashLoan(
|
|
paraswapLiquiditySwapAdapter.address,
|
|
[weth.address],
|
|
[amountWETHtoSwap],
|
|
[0],
|
|
userAddress,
|
|
params,
|
|
0
|
|
)
|
|
)
|
|
.to.emit(paraswapLiquiditySwapAdapter, 'Swapped')
|
|
.withArgs(weth.address, dai.address, amountWETHtoSwap, expectedDaiAmount);
|
|
|
|
const adapterWethBalance = await weth.balanceOf(paraswapLiquiditySwapAdapter.address);
|
|
const adapterDaiBalance = await dai.balanceOf(paraswapLiquiditySwapAdapter.address);
|
|
const userADaiBalance = await aDai.balanceOf(userAddress);
|
|
const userAEthBalance = await aWETH.balanceOf(userAddress);
|
|
|
|
// N.B. will get some portion of flashloan premium back from the pool
|
|
expect(adapterWethBalance).to.be.eq(Zero);
|
|
expect(adapterDaiBalance).to.be.eq(Zero);
|
|
expect(userADaiBalance).to.be.eq(expectedDaiAmount);
|
|
expect(userAEthBalance).to.be.gt(userAEthBalanceBefore.sub(flashloanTotal));
|
|
expect(userAEthBalance).to.be.lt(userAEthBalanceBefore.mul(10001).div(10000).sub(amountWETHtoSwap));
|
|
});
|
|
|
|
it('should correctly swap tokens using permit', async () => {
|
|
const {
|
|
users,
|
|
weth,
|
|
oracle,
|
|
dai,
|
|
aDai,
|
|
aWETH,
|
|
pool,
|
|
paraswapLiquiditySwapAdapter,
|
|
} = testEnv;
|
|
const user = users[0].signer;
|
|
const userAddress = users[0].address;
|
|
|
|
const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
|
|
|
|
const daiPrice = await oracle.getAssetPrice(dai.address);
|
|
const expectedDaiAmount = await convertToCurrencyDecimals(
|
|
dai.address,
|
|
new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
|
|
);
|
|
|
|
await mockAugustus.expectSwap(weth.address, dai.address, amountWETHtoSwap, amountWETHtoSwap, expectedDaiAmount);
|
|
|
|
const flashloanPremium = amountWETHtoSwap.mul(9).div(10000);
|
|
const flashloanTotal = amountWETHtoSwap.add(flashloanPremium);
|
|
|
|
// User will swap liquidity aEth to aDai
|
|
const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
|
|
|
|
const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID;
|
|
const deadline = MAX_UINT_AMOUNT;
|
|
const nonce = (await aWETH._nonces(userAddress)).toNumber();
|
|
const msgParams = buildPermitParams(
|
|
chainId,
|
|
aWETH.address,
|
|
'1',
|
|
await aWETH.name(),
|
|
userAddress,
|
|
paraswapLiquiditySwapAdapter.address,
|
|
nonce,
|
|
deadline,
|
|
flashloanTotal.toString()
|
|
);
|
|
|
|
const ownerPrivateKey = require('../test-wallets.js').accounts[1].secretKey;
|
|
if (!ownerPrivateKey) {
|
|
throw new Error('INVALID_OWNER_PK');
|
|
}
|
|
|
|
const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams);
|
|
|
|
const mockAugustusCalldata = mockAugustus.interface.encodeFunctionData(
|
|
'swap',
|
|
[weth.address, dai.address, amountWETHtoSwap, expectedDaiAmount]
|
|
);
|
|
|
|
const params = buildParaSwapLiquiditySwapParams(
|
|
dai.address,
|
|
expectedDaiAmount,
|
|
0,
|
|
mockAugustusCalldata,
|
|
mockAugustus.address,
|
|
flashloanTotal,
|
|
deadline,
|
|
v,
|
|
r,
|
|
s
|
|
);
|
|
|
|
await expect(
|
|
pool
|
|
.connect(user)
|
|
.flashLoan(
|
|
paraswapLiquiditySwapAdapter.address,
|
|
[weth.address],
|
|
[amountWETHtoSwap],
|
|
[0],
|
|
userAddress,
|
|
params,
|
|
0
|
|
)
|
|
)
|
|
.to.emit(paraswapLiquiditySwapAdapter, 'Swapped')
|
|
.withArgs(weth.address, dai.address, amountWETHtoSwap, expectedDaiAmount);
|
|
|
|
const adapterWethBalance = await weth.balanceOf(paraswapLiquiditySwapAdapter.address);
|
|
const adapterDaiBalance = await dai.balanceOf(paraswapLiquiditySwapAdapter.address);
|
|
const userADaiBalance = await aDai.balanceOf(userAddress);
|
|
const userAEthBalance = await aWETH.balanceOf(userAddress);
|
|
|
|
// N.B. will get some portion of flashloan premium back from the pool
|
|
expect(adapterWethBalance).to.be.eq(Zero);
|
|
expect(adapterDaiBalance).to.be.eq(Zero);
|
|
expect(userADaiBalance).to.be.eq(expectedDaiAmount);
|
|
expect(userAEthBalance).to.be.gt(userAEthBalanceBefore.sub(flashloanTotal));
|
|
expect(userAEthBalance).to.be.lt(userAEthBalanceBefore.mul(10001).div(10000).sub(amountWETHtoSwap));
|
|
});
|
|
|
|
it('should correctly swap tokens all the balance', async () => {
|
|
const {
|
|
users,
|
|
weth,
|
|
oracle,
|
|
dai,
|
|
aDai,
|
|
aWETH,
|
|
pool,
|
|
paraswapLiquiditySwapAdapter,
|
|
} = testEnv;
|
|
const user = users[0].signer;
|
|
const userAddress = users[0].address;
|
|
|
|
const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
|
|
|
|
const daiPrice = await oracle.getAssetPrice(dai.address);
|
|
const expectedDaiAmount = await convertToCurrencyDecimals(
|
|
dai.address,
|
|
new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
|
|
);
|
|
|
|
await mockAugustus.expectSwap(weth.address, dai.address, amountWETHtoSwap.add(1), amountWETHtoSwap.mul(10001).div(10000), expectedDaiAmount);
|
|
|
|
const bigAmountToSwap = parseEther('11');
|
|
const flashloanPremium = bigAmountToSwap.mul(9).div(10000);
|
|
const flashloanTotal = bigAmountToSwap.add(flashloanPremium);
|
|
|
|
// Remove other balance
|
|
await aWETH.connect(user).transfer(users[1].address, parseEther('90').sub(flashloanPremium));
|
|
|
|
// User will swap liquidity aEth to aDai
|
|
await aWETH.connect(user).approve(paraswapLiquiditySwapAdapter.address, flashloanTotal);
|
|
|
|
const mockAugustusCalldata = mockAugustus.interface.encodeFunctionData(
|
|
'swap',
|
|
[weth.address, dai.address, bigAmountToSwap, expectedDaiAmount]
|
|
);
|
|
|
|
const params = buildParaSwapLiquiditySwapParams(
|
|
dai.address,
|
|
expectedDaiAmount,
|
|
4 + 2*32,
|
|
mockAugustusCalldata,
|
|
mockAugustus.address,
|
|
0,
|
|
0,
|
|
0,
|
|
'0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
'0x0000000000000000000000000000000000000000000000000000000000000000'
|
|
);
|
|
|
|
await expect(
|
|
pool
|
|
.connect(user)
|
|
.flashLoan(
|
|
paraswapLiquiditySwapAdapter.address,
|
|
[weth.address],
|
|
[bigAmountToSwap],
|
|
[0],
|
|
userAddress,
|
|
params,
|
|
0
|
|
)
|
|
).to.emit(paraswapLiquiditySwapAdapter, 'Swapped');
|
|
|
|
const adapterWethBalance = await weth.balanceOf(paraswapLiquiditySwapAdapter.address);
|
|
const adapterDaiBalance = await dai.balanceOf(paraswapLiquiditySwapAdapter.address);
|
|
const userADaiBalance = await aDai.balanceOf(userAddress);
|
|
const userAEthBalance = await aWETH.balanceOf(userAddress);
|
|
|
|
expect(adapterWethBalance).to.be.eq(Zero);
|
|
expect(adapterDaiBalance).to.be.eq(Zero);
|
|
expect(userADaiBalance).to.be.eq(expectedDaiAmount);
|
|
expect(userAEthBalance).to.be.eq(Zero);
|
|
});
|
|
|
|
it('should correctly swap tokens all the balance using permit', async () => {
|
|
const {
|
|
users,
|
|
weth,
|
|
oracle,
|
|
dai,
|
|
aDai,
|
|
aWETH,
|
|
pool,
|
|
paraswapLiquiditySwapAdapter,
|
|
} = testEnv;
|
|
const user = users[0].signer;
|
|
const userAddress = users[0].address;
|
|
|
|
const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
|
|
|
|
const daiPrice = await oracle.getAssetPrice(dai.address);
|
|
const expectedDaiAmount = await convertToCurrencyDecimals(
|
|
dai.address,
|
|
new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
|
|
);
|
|
|
|
await mockAugustus.expectSwap(weth.address, dai.address, amountWETHtoSwap.add(1), amountWETHtoSwap.mul(10001).div(10000), expectedDaiAmount);
|
|
|
|
const bigAmountToSwap = parseEther('11');
|
|
const flashloanPremium = bigAmountToSwap.mul(9).div(10000);
|
|
const flashloanTotal = bigAmountToSwap.add(flashloanPremium);
|
|
|
|
// Remove other balance
|
|
await aWETH.connect(user).transfer(users[1].address, parseEther('90').sub(flashloanPremium));
|
|
|
|
// User will swap liquidity aEth to aDai
|
|
const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID;
|
|
const deadline = MAX_UINT_AMOUNT;
|
|
const nonce = (await aWETH._nonces(userAddress)).toNumber();
|
|
const msgParams = buildPermitParams(
|
|
chainId,
|
|
aWETH.address,
|
|
'1',
|
|
await aWETH.name(),
|
|
userAddress,
|
|
paraswapLiquiditySwapAdapter.address,
|
|
nonce,
|
|
deadline,
|
|
flashloanTotal.toString()
|
|
);
|
|
|
|
const ownerPrivateKey = require('../test-wallets.js').accounts[1].secretKey;
|
|
if (!ownerPrivateKey) {
|
|
throw new Error('INVALID_OWNER_PK');
|
|
}
|
|
|
|
const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams);
|
|
|
|
const mockAugustusCalldata = mockAugustus.interface.encodeFunctionData(
|
|
'swap',
|
|
[weth.address, dai.address, bigAmountToSwap, expectedDaiAmount]
|
|
);
|
|
|
|
const params = buildParaSwapLiquiditySwapParams(
|
|
dai.address,
|
|
expectedDaiAmount,
|
|
4 + 2*32,
|
|
mockAugustusCalldata,
|
|
mockAugustus.address,
|
|
flashloanTotal,
|
|
deadline,
|
|
v,
|
|
r,
|
|
s
|
|
);
|
|
|
|
await expect(
|
|
pool
|
|
.connect(user)
|
|
.flashLoan(
|
|
paraswapLiquiditySwapAdapter.address,
|
|
[weth.address],
|
|
[bigAmountToSwap],
|
|
[0],
|
|
userAddress,
|
|
params,
|
|
0
|
|
)
|
|
).to.emit(paraswapLiquiditySwapAdapter, 'Swapped');
|
|
|
|
const adapterWethBalance = await weth.balanceOf(paraswapLiquiditySwapAdapter.address);
|
|
const adapterDaiBalance = await dai.balanceOf(paraswapLiquiditySwapAdapter.address);
|
|
const userADaiBalance = await aDai.balanceOf(userAddress);
|
|
const userAEthBalance = await aWETH.balanceOf(userAddress);
|
|
|
|
expect(adapterWethBalance).to.be.eq(Zero);
|
|
expect(adapterDaiBalance).to.be.eq(Zero);
|
|
expect(userADaiBalance).to.be.eq(expectedDaiAmount);
|
|
expect(userAEthBalance).to.be.eq(Zero);
|
|
});
|
|
});
|
|
|
|
describe('swapAndDeposit', () => {
|
|
beforeEach(async () => {
|
|
const { users, weth, dai, pool, deployer } = testEnv;
|
|
const userAddress = users[0].address;
|
|
|
|
// Provide liquidity
|
|
await dai.mint(parseEther('20000'));
|
|
await dai.approve(pool.address, parseEther('20000'));
|
|
await pool.deposit(dai.address, parseEther('20000'), deployer.address, 0);
|
|
|
|
await weth.mint(parseEther('10000'));
|
|
await weth.approve(pool.address, parseEther('10000'));
|
|
await pool.deposit(weth.address, parseEther('10000'), deployer.address, 0);
|
|
|
|
// Make a deposit for user
|
|
await weth.mint(parseEther('100'));
|
|
await weth.approve(pool.address, parseEther('100'));
|
|
await pool.deposit(weth.address, parseEther('100'), userAddress, 0);
|
|
});
|
|
|
|
it('should correctly swap tokens and deposit the out tokens in the pool', async () => {
|
|
const { users, weth, oracle, dai, aDai, aWETH, paraswapLiquiditySwapAdapter } = testEnv;
|
|
const user = users[0].signer;
|
|
const userAddress = users[0].address;
|
|
|
|
const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
|
|
|
|
const daiPrice = await oracle.getAssetPrice(dai.address);
|
|
const expectedDaiAmount = await convertToCurrencyDecimals(
|
|
dai.address,
|
|
new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
|
|
);
|
|
|
|
await mockAugustus.expectSwap(weth.address, dai.address, amountWETHtoSwap, amountWETHtoSwap, expectedDaiAmount);
|
|
|
|
// User will swap liquidity aEth to aDai
|
|
const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
|
|
await aWETH.connect(user).approve(paraswapLiquiditySwapAdapter.address, amountWETHtoSwap);
|
|
|
|
const mockAugustusCalldata = mockAugustus.interface.encodeFunctionData(
|
|
'swap',
|
|
[weth.address, dai.address, amountWETHtoSwap, expectedDaiAmount]
|
|
);
|
|
|
|
await expect(
|
|
paraswapLiquiditySwapAdapter.connect(user).swapAndDeposit(
|
|
weth.address,
|
|
dai.address,
|
|
amountWETHtoSwap,
|
|
expectedDaiAmount,
|
|
0,
|
|
mockAugustusCalldata,
|
|
mockAugustus.address,
|
|
{
|
|
amount: 0,
|
|
deadline: 0,
|
|
v: 0,
|
|
r: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
s: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
}
|
|
)
|
|
)
|
|
.to.emit(paraswapLiquiditySwapAdapter, 'Swapped')
|
|
.withArgs(weth.address, dai.address, amountWETHtoSwap, expectedDaiAmount);
|
|
|
|
const adapterWethBalance = await weth.balanceOf(paraswapLiquiditySwapAdapter.address);
|
|
const adapterDaiBalance = await dai.balanceOf(paraswapLiquiditySwapAdapter.address);
|
|
const userADaiBalance = await aDai.balanceOf(userAddress);
|
|
const userAEthBalance = await aWETH.balanceOf(userAddress);
|
|
|
|
expect(adapterWethBalance).to.be.eq(Zero);
|
|
expect(adapterDaiBalance).to.be.eq(Zero);
|
|
expect(userADaiBalance).to.be.eq(expectedDaiAmount);
|
|
expect(userAEthBalance).to.be.eq(userAEthBalanceBefore.sub(amountWETHtoSwap));
|
|
});
|
|
|
|
it('should correctly swap tokens using permit', async () => {
|
|
const { users, weth, oracle, dai, aDai, aWETH, paraswapLiquiditySwapAdapter } = testEnv;
|
|
const user = users[0].signer;
|
|
const userAddress = users[0].address;
|
|
|
|
const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
|
|
|
|
const daiPrice = await oracle.getAssetPrice(dai.address);
|
|
const expectedDaiAmount = await convertToCurrencyDecimals(
|
|
dai.address,
|
|
new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
|
|
);
|
|
|
|
await mockAugustus.expectSwap(weth.address, dai.address, amountWETHtoSwap, amountWETHtoSwap, expectedDaiAmount);
|
|
|
|
// User will swap liquidity aEth to aDai
|
|
const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
|
|
|
|
const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID;
|
|
const deadline = MAX_UINT_AMOUNT;
|
|
const nonce = (await aWETH._nonces(userAddress)).toNumber();
|
|
const msgParams = buildPermitParams(
|
|
chainId,
|
|
aWETH.address,
|
|
'1',
|
|
await aWETH.name(),
|
|
userAddress,
|
|
paraswapLiquiditySwapAdapter.address,
|
|
nonce,
|
|
deadline,
|
|
amountWETHtoSwap.toString()
|
|
);
|
|
|
|
const ownerPrivateKey = require('../test-wallets.js').accounts[1].secretKey;
|
|
if (!ownerPrivateKey) {
|
|
throw new Error('INVALID_OWNER_PK');
|
|
}
|
|
|
|
const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams);
|
|
|
|
const mockAugustusCalldata = mockAugustus.interface.encodeFunctionData(
|
|
'swap',
|
|
[weth.address, dai.address, amountWETHtoSwap, expectedDaiAmount]
|
|
);
|
|
|
|
await expect(
|
|
paraswapLiquiditySwapAdapter.connect(user).swapAndDeposit(
|
|
weth.address,
|
|
dai.address,
|
|
amountWETHtoSwap,
|
|
expectedDaiAmount,
|
|
0,
|
|
mockAugustusCalldata,
|
|
mockAugustus.address,
|
|
{
|
|
amount: amountWETHtoSwap,
|
|
deadline,
|
|
v,
|
|
r,
|
|
s,
|
|
}
|
|
)
|
|
)
|
|
.to.emit(paraswapLiquiditySwapAdapter, 'Swapped')
|
|
.withArgs(weth.address, dai.address, amountWETHtoSwap, expectedDaiAmount);
|
|
|
|
const adapterWethBalance = await weth.balanceOf(paraswapLiquiditySwapAdapter.address);
|
|
const adapterDaiBalance = await dai.balanceOf(paraswapLiquiditySwapAdapter.address);
|
|
const userADaiBalance = await aDai.balanceOf(userAddress);
|
|
const userAEthBalance = await aWETH.balanceOf(userAddress);
|
|
|
|
expect(adapterWethBalance).to.be.eq(Zero);
|
|
expect(adapterDaiBalance).to.be.eq(Zero);
|
|
expect(userADaiBalance).to.be.eq(expectedDaiAmount);
|
|
expect(userAEthBalance).to.be.eq(userAEthBalanceBefore.sub(amountWETHtoSwap));
|
|
});
|
|
|
|
it('should revert when trying to swap more than balance', async () => {
|
|
const { users, weth, oracle, dai, aWETH, paraswapLiquiditySwapAdapter } = testEnv;
|
|
const user = users[0].signer;
|
|
const userAddress = users[0].address;
|
|
|
|
const amountWETHtoSwap = (await convertToCurrencyDecimals(weth.address, '100')).add(1);
|
|
|
|
const daiPrice = await oracle.getAssetPrice(dai.address);
|
|
const expectedDaiAmount = await convertToCurrencyDecimals(
|
|
dai.address,
|
|
new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
|
|
);
|
|
|
|
await mockAugustus.expectSwap(weth.address, dai.address, amountWETHtoSwap, amountWETHtoSwap, expectedDaiAmount);
|
|
|
|
// User will swap liquidity aEth to aDai
|
|
await aWETH.connect(user).approve(paraswapLiquiditySwapAdapter.address, amountWETHtoSwap);
|
|
|
|
const mockAugustusCalldata = mockAugustus.interface.encodeFunctionData(
|
|
'swap',
|
|
[weth.address, dai.address, amountWETHtoSwap, expectedDaiAmount]
|
|
);
|
|
|
|
await expect(
|
|
paraswapLiquiditySwapAdapter.connect(user).swapAndDeposit(
|
|
weth.address,
|
|
dai.address,
|
|
amountWETHtoSwap,
|
|
expectedDaiAmount,
|
|
0,
|
|
mockAugustusCalldata,
|
|
mockAugustus.address,
|
|
{
|
|
amount: 0,
|
|
deadline: 0,
|
|
v: 0,
|
|
r: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
s: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
}
|
|
)
|
|
).to.be.revertedWith('SafeERC20: low-level call failed');
|
|
});
|
|
|
|
it('should revert when trying to swap more than allowance', async () => {
|
|
const { users, weth, oracle, dai, aWETH, paraswapLiquiditySwapAdapter } = testEnv;
|
|
const user = users[0].signer;
|
|
const userAddress = users[0].address;
|
|
|
|
const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
|
|
|
|
const daiPrice = await oracle.getAssetPrice(dai.address);
|
|
const expectedDaiAmount = await convertToCurrencyDecimals(
|
|
dai.address,
|
|
new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
|
|
);
|
|
|
|
await mockAugustus.expectSwap(weth.address, dai.address, amountWETHtoSwap, amountWETHtoSwap, expectedDaiAmount);
|
|
|
|
// User will swap liquidity aEth to aDai
|
|
await aWETH.connect(user).approve(paraswapLiquiditySwapAdapter.address, amountWETHtoSwap.sub(1));
|
|
|
|
const mockAugustusCalldata = mockAugustus.interface.encodeFunctionData(
|
|
'swap',
|
|
[weth.address, dai.address, amountWETHtoSwap, expectedDaiAmount]
|
|
);
|
|
|
|
await expect(
|
|
paraswapLiquiditySwapAdapter.connect(user).swapAndDeposit(
|
|
weth.address,
|
|
dai.address,
|
|
amountWETHtoSwap,
|
|
expectedDaiAmount,
|
|
0,
|
|
mockAugustusCalldata,
|
|
mockAugustus.address,
|
|
{
|
|
amount: 0,
|
|
deadline: 0,
|
|
v: 0,
|
|
r: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
s: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
}
|
|
)
|
|
).to.be.revertedWith('SafeERC20: low-level call failed');
|
|
});
|
|
|
|
it('should revert when min amount to receive exceeds the max slippage amount', async () => {
|
|
const { users, weth, oracle, dai, aWETH, paraswapLiquiditySwapAdapter } = testEnv;
|
|
const user = users[0].signer;
|
|
|
|
const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
|
|
|
|
const daiPrice = await oracle.getAssetPrice(dai.address);
|
|
const expectedDaiAmount = await convertToCurrencyDecimals(
|
|
dai.address,
|
|
new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
|
|
);
|
|
|
|
await mockAugustus.expectSwap(weth.address, dai.address, amountWETHtoSwap, amountWETHtoSwap, expectedDaiAmount);
|
|
|
|
const smallExpectedDaiAmount = expectedDaiAmount.div(2);
|
|
|
|
// User will swap liquidity aEth to aDai
|
|
await aWETH.connect(user).approve(paraswapLiquiditySwapAdapter.address, amountWETHtoSwap);
|
|
|
|
const mockAugustusCalldata = mockAugustus.interface.encodeFunctionData(
|
|
'swap',
|
|
[weth.address, dai.address, amountWETHtoSwap, expectedDaiAmount]
|
|
);
|
|
|
|
await expect(
|
|
paraswapLiquiditySwapAdapter.connect(user).swapAndDeposit(
|
|
weth.address,
|
|
dai.address,
|
|
amountWETHtoSwap,
|
|
smallExpectedDaiAmount,
|
|
0,
|
|
mockAugustusCalldata,
|
|
mockAugustus.address,
|
|
{
|
|
amount: 0,
|
|
deadline: 0,
|
|
v: 0,
|
|
r: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
s: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
}
|
|
)
|
|
).to.be.revertedWith('MIN_AMOUNT_EXCEEDS_MAX_SLIPPAGE');
|
|
});
|
|
|
|
it('should bubble up errors from Augustus', async () => {
|
|
const { users, weth, oracle, dai, aWETH, paraswapLiquiditySwapAdapter } = testEnv;
|
|
const user = users[0].signer;
|
|
|
|
const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
|
|
|
|
const daiPrice = await oracle.getAssetPrice(dai.address);
|
|
const expectedDaiAmount = await convertToCurrencyDecimals(
|
|
dai.address,
|
|
new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
|
|
);
|
|
|
|
await mockAugustus.expectSwap(weth.address, dai.address, amountWETHtoSwap, amountWETHtoSwap, expectedDaiAmount);
|
|
|
|
// User will swap liquidity aEth to aDai
|
|
await aWETH.connect(user).approve(paraswapLiquiditySwapAdapter.address, amountWETHtoSwap);
|
|
|
|
// Add 1 to expected amount so it will fail
|
|
const mockAugustusCalldata = mockAugustus.interface.encodeFunctionData(
|
|
'swap',
|
|
[weth.address, dai.address, amountWETHtoSwap, expectedDaiAmount.add(1)]
|
|
);
|
|
|
|
await expect(
|
|
paraswapLiquiditySwapAdapter.connect(user).swapAndDeposit(
|
|
weth.address,
|
|
dai.address,
|
|
amountWETHtoSwap,
|
|
expectedDaiAmount,
|
|
0,
|
|
mockAugustusCalldata,
|
|
mockAugustus.address,
|
|
{
|
|
amount: 0,
|
|
deadline: 0,
|
|
v: 0,
|
|
r: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
s: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
}
|
|
)
|
|
).to.be.revertedWith('Received amount of tokens are less than expected');
|
|
});
|
|
|
|
it('should revert if Augustus swaps for less than minimum to receive', async () => {
|
|
const { users, weth, oracle, dai, aWETH, paraswapLiquiditySwapAdapter } = testEnv;
|
|
const user = users[0].signer;
|
|
const userAddress = users[0].address;
|
|
|
|
const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
|
|
|
|
const daiPrice = await oracle.getAssetPrice(dai.address);
|
|
const expectedDaiAmount = await convertToCurrencyDecimals(
|
|
dai.address,
|
|
new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
|
|
);
|
|
const actualDaiAmount = expectedDaiAmount.sub(1);
|
|
|
|
await mockAugustus.expectSwap(weth.address, dai.address, amountWETHtoSwap, amountWETHtoSwap, actualDaiAmount);
|
|
|
|
// User will swap liquidity aEth to aDai
|
|
await aWETH.connect(user).approve(paraswapLiquiditySwapAdapter.address, amountWETHtoSwap);
|
|
|
|
const mockAugustusCalldata = mockAugustus.interface.encodeFunctionData(
|
|
'swap',
|
|
[weth.address, dai.address, amountWETHtoSwap, actualDaiAmount]
|
|
);
|
|
|
|
await expect(
|
|
paraswapLiquiditySwapAdapter.connect(user).swapAndDeposit(
|
|
weth.address,
|
|
dai.address,
|
|
amountWETHtoSwap,
|
|
expectedDaiAmount,
|
|
0,
|
|
mockAugustusCalldata,
|
|
mockAugustus.address,
|
|
{
|
|
amount: 0,
|
|
deadline: 0,
|
|
v: 0,
|
|
r: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
s: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
}
|
|
)
|
|
).to.be.revertedWith('INSUFFICIENT_AMOUNT_RECEIVED');
|
|
});
|
|
|
|
it("should revert if Augustus doesn't swap correct amount", async () => {
|
|
const { users, weth, oracle, dai, aWETH, paraswapLiquiditySwapAdapter } = testEnv;
|
|
const user = users[0].signer;
|
|
const userAddress = users[0].address;
|
|
|
|
const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
|
|
|
|
const daiPrice = await oracle.getAssetPrice(dai.address);
|
|
const expectedDaiAmount = await convertToCurrencyDecimals(
|
|
dai.address,
|
|
new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
|
|
);
|
|
|
|
const augustusSwapAmount = amountWETHtoSwap.sub(1);
|
|
|
|
await mockAugustus.expectSwap(weth.address, dai.address, augustusSwapAmount, augustusSwapAmount, expectedDaiAmount);
|
|
|
|
// User will swap liquidity aEth to aDai
|
|
await aWETH.connect(user).approve(paraswapLiquiditySwapAdapter.address, amountWETHtoSwap);
|
|
|
|
const mockAugustusCalldata = mockAugustus.interface.encodeFunctionData(
|
|
'swap',
|
|
[weth.address, dai.address, augustusSwapAmount, expectedDaiAmount]
|
|
);
|
|
|
|
await expect(
|
|
paraswapLiquiditySwapAdapter.connect(user).swapAndDeposit(
|
|
weth.address,
|
|
dai.address,
|
|
amountWETHtoSwap,
|
|
expectedDaiAmount,
|
|
0,
|
|
mockAugustusCalldata,
|
|
mockAugustus.address,
|
|
{
|
|
amount: 0,
|
|
deadline: 0,
|
|
v: 0,
|
|
r: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
s: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
}
|
|
)
|
|
).to.be.revertedWith('WRONG_BALANCE_AFTER_SWAP');
|
|
});
|
|
|
|
it('should correctly swap all the balance when using a bigger amount', async () => {
|
|
const { users, weth, oracle, dai, aDai, aWETH, paraswapLiquiditySwapAdapter } = testEnv;
|
|
const user = users[0].signer;
|
|
const userAddress = users[0].address;
|
|
|
|
const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
|
|
|
|
const daiPrice = await oracle.getAssetPrice(dai.address);
|
|
const expectedDaiAmount = await convertToCurrencyDecimals(
|
|
dai.address,
|
|
new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
|
|
);
|
|
|
|
await mockAugustus.expectSwap(weth.address, dai.address, amountWETHtoSwap, amountWETHtoSwap, expectedDaiAmount);
|
|
|
|
// Remove other balance
|
|
await aWETH.connect(user).transfer(users[1].address, parseEther('90'));
|
|
|
|
// User will swap liquidity aEth to aDai
|
|
const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
|
|
expect(userAEthBalanceBefore).to.be.eq(amountWETHtoSwap);
|
|
|
|
const bigAmountToSwap = parseEther('11');
|
|
await aWETH.connect(user).approve(paraswapLiquiditySwapAdapter.address, bigAmountToSwap);
|
|
|
|
const mockAugustusCalldata = mockAugustus.interface.encodeFunctionData(
|
|
'swap',
|
|
[weth.address, dai.address, bigAmountToSwap, expectedDaiAmount]
|
|
);
|
|
|
|
await expect(
|
|
paraswapLiquiditySwapAdapter.connect(user).swapAndDeposit(
|
|
weth.address,
|
|
dai.address,
|
|
bigAmountToSwap,
|
|
expectedDaiAmount,
|
|
4 + 2*32,
|
|
mockAugustusCalldata,
|
|
mockAugustus.address,
|
|
{
|
|
amount: 0,
|
|
deadline: 0,
|
|
v: 0,
|
|
r: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
s: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
}
|
|
)
|
|
)
|
|
.to.emit(paraswapLiquiditySwapAdapter, 'Swapped')
|
|
.withArgs(weth.address, dai.address, amountWETHtoSwap, expectedDaiAmount);
|
|
|
|
const adapterWethBalance = await weth.balanceOf(paraswapLiquiditySwapAdapter.address);
|
|
const adapterDaiBalance = await dai.balanceOf(paraswapLiquiditySwapAdapter.address);
|
|
const userADaiBalance = await aDai.balanceOf(userAddress);
|
|
const userAEthBalance = await aWETH.balanceOf(userAddress);
|
|
|
|
expect(adapterWethBalance).to.be.eq(Zero);
|
|
expect(adapterDaiBalance).to.be.eq(Zero);
|
|
expect(userADaiBalance).to.be.eq(expectedDaiAmount);
|
|
expect(userAEthBalance).to.be.eq(Zero);
|
|
});
|
|
|
|
it('should correctly swap all the balance when using permit', async () => {
|
|
const { users, weth, oracle, dai, aDai, aWETH, paraswapLiquiditySwapAdapter } = testEnv;
|
|
const user = users[0].signer;
|
|
const userAddress = users[0].address;
|
|
|
|
const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
|
|
|
|
const daiPrice = await oracle.getAssetPrice(dai.address);
|
|
const expectedDaiAmount = await convertToCurrencyDecimals(
|
|
dai.address,
|
|
new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
|
|
);
|
|
|
|
await mockAugustus.expectSwap(weth.address, dai.address, amountWETHtoSwap, amountWETHtoSwap, expectedDaiAmount);
|
|
|
|
// Remove other balance
|
|
await aWETH.connect(user).transfer(users[1].address, parseEther('90'));
|
|
|
|
// User will swap liquidity aEth to aDai
|
|
const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
|
|
expect(userAEthBalanceBefore).to.be.eq(amountWETHtoSwap);
|
|
|
|
const bigAmountToSwap = parseEther('11');
|
|
|
|
const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID;
|
|
const deadline = MAX_UINT_AMOUNT;
|
|
const nonce = (await aWETH._nonces(userAddress)).toNumber();
|
|
const msgParams = buildPermitParams(
|
|
chainId,
|
|
aWETH.address,
|
|
'1',
|
|
await aWETH.name(),
|
|
userAddress,
|
|
paraswapLiquiditySwapAdapter.address,
|
|
nonce,
|
|
deadline,
|
|
bigAmountToSwap.toString()
|
|
);
|
|
|
|
const ownerPrivateKey = require('../test-wallets.js').accounts[1].secretKey;
|
|
if (!ownerPrivateKey) {
|
|
throw new Error('INVALID_OWNER_PK');
|
|
}
|
|
|
|
const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams);
|
|
|
|
const mockAugustusCalldata = mockAugustus.interface.encodeFunctionData(
|
|
'swap',
|
|
[weth.address, dai.address, bigAmountToSwap, expectedDaiAmount]
|
|
);
|
|
|
|
await expect(
|
|
paraswapLiquiditySwapAdapter.connect(user).swapAndDeposit(
|
|
weth.address,
|
|
dai.address,
|
|
bigAmountToSwap,
|
|
expectedDaiAmount,
|
|
4 + 2*32,
|
|
mockAugustusCalldata,
|
|
mockAugustus.address,
|
|
{
|
|
amount: bigAmountToSwap,
|
|
deadline,
|
|
v,
|
|
r,
|
|
s,
|
|
}
|
|
)
|
|
)
|
|
.to.emit(paraswapLiquiditySwapAdapter, 'Swapped')
|
|
.withArgs(weth.address, dai.address, amountWETHtoSwap, expectedDaiAmount);
|
|
|
|
const adapterWethBalance = await weth.balanceOf(paraswapLiquiditySwapAdapter.address);
|
|
const adapterDaiBalance = await dai.balanceOf(paraswapLiquiditySwapAdapter.address);
|
|
const userADaiBalance = await aDai.balanceOf(userAddress);
|
|
const userAEthBalance = await aWETH.balanceOf(userAddress);
|
|
|
|
expect(adapterWethBalance).to.be.eq(Zero);
|
|
expect(adapterDaiBalance).to.be.eq(Zero);
|
|
expect(userADaiBalance).to.be.eq(expectedDaiAmount);
|
|
expect(userAEthBalance).to.be.eq(Zero);
|
|
});
|
|
|
|
it('should revert trying to swap all the balance when using a smaller amount', async () => {
|
|
const { users, weth, oracle, dai, aWETH, paraswapLiquiditySwapAdapter } = testEnv;
|
|
const user = users[0].signer;
|
|
const userAddress = users[0].address;
|
|
|
|
const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
|
|
|
|
const daiPrice = await oracle.getAssetPrice(dai.address);
|
|
const expectedDaiAmount = await convertToCurrencyDecimals(
|
|
dai.address,
|
|
new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
|
|
);
|
|
|
|
await mockAugustus.expectSwap(weth.address, dai.address, amountWETHtoSwap, amountWETHtoSwap, expectedDaiAmount);
|
|
|
|
// Remove other balance
|
|
await aWETH.connect(user).transfer(users[1].address, parseEther('90'));
|
|
|
|
// User will swap liquidity aEth to aDai
|
|
const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
|
|
expect(userAEthBalanceBefore).to.be.eq(amountWETHtoSwap);
|
|
|
|
const smallAmountToSwap = parseEther('10').sub(1);
|
|
await aWETH.connect(user).approve(paraswapLiquiditySwapAdapter.address, smallAmountToSwap);
|
|
|
|
const mockAugustusCalldata = mockAugustus.interface.encodeFunctionData(
|
|
'swap',
|
|
[weth.address, dai.address, smallAmountToSwap, expectedDaiAmount]
|
|
);
|
|
|
|
await expect(
|
|
paraswapLiquiditySwapAdapter.connect(user).swapAndDeposit(
|
|
weth.address,
|
|
dai.address,
|
|
smallAmountToSwap,
|
|
expectedDaiAmount,
|
|
4 + 2*32,
|
|
mockAugustusCalldata,
|
|
mockAugustus.address,
|
|
{
|
|
amount: 0,
|
|
deadline: 0,
|
|
v: 0,
|
|
r: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
s: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
}
|
|
)
|
|
).to.be.revertedWith('INSUFFICIENT_AMOUNT_TO_SWAP');
|
|
});
|
|
|
|
it('should not touch any token balance already in the adapter', async () => {
|
|
const { users, weth, oracle, dai, aDai, aWETH, paraswapLiquiditySwapAdapter } = testEnv;
|
|
const user = users[0].signer;
|
|
const userAddress = users[0].address;
|
|
|
|
// Put token balances in the adapter
|
|
const adapterWethBalanceBefore = parseEther('123');
|
|
await weth.mint(adapterWethBalanceBefore);
|
|
await weth.transfer(paraswapLiquiditySwapAdapter.address, adapterWethBalanceBefore);
|
|
const adapterDaiBalanceBefore = parseEther('234');
|
|
await dai.mint(adapterDaiBalanceBefore);
|
|
await dai.transfer(paraswapLiquiditySwapAdapter.address, adapterDaiBalanceBefore);
|
|
|
|
const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
|
|
|
|
const daiPrice = await oracle.getAssetPrice(dai.address);
|
|
const expectedDaiAmount = await convertToCurrencyDecimals(
|
|
dai.address,
|
|
new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
|
|
);
|
|
|
|
await mockAugustus.expectSwap(weth.address, dai.address, amountWETHtoSwap, amountWETHtoSwap, expectedDaiAmount);
|
|
|
|
// User will swap liquidity aEth to aDai
|
|
const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
|
|
await aWETH.connect(user).approve(paraswapLiquiditySwapAdapter.address, amountWETHtoSwap);
|
|
|
|
const mockAugustusCalldata = mockAugustus.interface.encodeFunctionData(
|
|
'swap',
|
|
[weth.address, dai.address, amountWETHtoSwap, expectedDaiAmount]
|
|
);
|
|
|
|
await expect(
|
|
paraswapLiquiditySwapAdapter.connect(user).swapAndDeposit(
|
|
weth.address,
|
|
dai.address,
|
|
amountWETHtoSwap,
|
|
expectedDaiAmount,
|
|
0,
|
|
mockAugustusCalldata,
|
|
mockAugustus.address,
|
|
{
|
|
amount: 0,
|
|
deadline: 0,
|
|
v: 0,
|
|
r: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
s: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
}
|
|
)
|
|
)
|
|
.to.emit(paraswapLiquiditySwapAdapter, 'Swapped')
|
|
.withArgs(weth.address, dai.address, amountWETHtoSwap, expectedDaiAmount);
|
|
|
|
const adapterWethBalance = await weth.balanceOf(paraswapLiquiditySwapAdapter.address);
|
|
const adapterDaiBalance = await dai.balanceOf(paraswapLiquiditySwapAdapter.address);
|
|
const userADaiBalance = await aDai.balanceOf(userAddress);
|
|
const userAEthBalance = await aWETH.balanceOf(userAddress);
|
|
|
|
expect(adapterWethBalance).to.be.eq(adapterWethBalanceBefore);
|
|
expect(adapterDaiBalance).to.be.eq(adapterDaiBalanceBefore);
|
|
expect(userADaiBalance).to.be.eq(expectedDaiAmount);
|
|
expect(userAEthBalance).to.be.eq(userAEthBalanceBefore.sub(amountWETHtoSwap));
|
|
});
|
|
});
|
|
|
|
describe('swapAndDeposit with borrowing', () => {
|
|
beforeEach(async () => {
|
|
const { users, weth, dai, pool, deployer } = testEnv;
|
|
const userAddress = users[0].address;
|
|
const borrower = users[1].signer;
|
|
const borrowerAddress = users[1].address;
|
|
|
|
// Provide liquidity
|
|
await dai.mint(parseEther('20000'));
|
|
await dai.approve(pool.address, parseEther('20000'));
|
|
await pool.deposit(dai.address, parseEther('20000'), deployer.address, 0);
|
|
|
|
await weth.mint(parseEther('10000'));
|
|
await weth.approve(pool.address, parseEther('10000'));
|
|
await pool.deposit(weth.address, parseEther('10000'), deployer.address, 0);
|
|
|
|
// Make a deposit for user
|
|
await weth.mint(parseEther('100'));
|
|
await weth.approve(pool.address, parseEther('100'));
|
|
await pool.deposit(weth.address, parseEther('100'), userAddress, 0);
|
|
|
|
// Add borrowing
|
|
const collateralAmount = parseEther('10000000');
|
|
await dai.mint(collateralAmount);
|
|
await dai.approve(pool.address, collateralAmount);
|
|
await pool.deposit(dai.address, collateralAmount, borrowerAddress, 0);
|
|
await pool.connect(borrower).borrow(weth.address, parseEther('5000'), 2, 0, borrowerAddress);
|
|
});
|
|
|
|
it('should correctly swap tokens and deposit the out tokens in the pool', async () => {
|
|
const { users, weth, oracle, dai, aDai, aWETH, paraswapLiquiditySwapAdapter } = testEnv;
|
|
const user = users[0].signer;
|
|
const userAddress = users[0].address;
|
|
|
|
const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
|
|
|
|
const daiPrice = await oracle.getAssetPrice(dai.address);
|
|
const expectedDaiAmount = await convertToCurrencyDecimals(
|
|
dai.address,
|
|
new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
|
|
);
|
|
|
|
await mockAugustus.expectSwap(weth.address, dai.address, amountWETHtoSwap, amountWETHtoSwap, expectedDaiAmount);
|
|
|
|
// User will swap liquidity aEth to aDai
|
|
const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
|
|
await aWETH.connect(user).approve(paraswapLiquiditySwapAdapter.address, amountWETHtoSwap);
|
|
|
|
const mockAugustusCalldata = mockAugustus.interface.encodeFunctionData(
|
|
'swap',
|
|
[weth.address, dai.address, amountWETHtoSwap, expectedDaiAmount]
|
|
);
|
|
|
|
await expect(
|
|
paraswapLiquiditySwapAdapter.connect(user).swapAndDeposit(
|
|
weth.address,
|
|
dai.address,
|
|
amountWETHtoSwap,
|
|
expectedDaiAmount,
|
|
0,
|
|
mockAugustusCalldata,
|
|
mockAugustus.address,
|
|
{
|
|
amount: 0,
|
|
deadline: 0,
|
|
v: 0,
|
|
r: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
s: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
}
|
|
)
|
|
)
|
|
.to.emit(paraswapLiquiditySwapAdapter, 'Swapped')
|
|
.withArgs(weth.address, dai.address, amountWETHtoSwap, expectedDaiAmount);
|
|
|
|
const adapterWethBalance = await weth.balanceOf(paraswapLiquiditySwapAdapter.address);
|
|
const adapterDaiBalance = await dai.balanceOf(paraswapLiquiditySwapAdapter.address);
|
|
const userADaiBalance = await aDai.balanceOf(userAddress);
|
|
const userAEthBalance = await aWETH.balanceOf(userAddress);
|
|
|
|
expect(adapterWethBalance).to.be.eq(Zero);
|
|
expect(adapterDaiBalance).to.be.eq(Zero);
|
|
expect(userADaiBalance).to.be.eq(expectedDaiAmount);
|
|
expect(userAEthBalance).to.be.gt(userAEthBalanceBefore.sub(amountWETHtoSwap));
|
|
expect(userAEthBalance).to.be.lt(userAEthBalanceBefore.mul(10001).div(10000).sub(amountWETHtoSwap));
|
|
});
|
|
|
|
it('should correctly swap tokens using permit', async () => {
|
|
const { users, weth, oracle, dai, aDai, aWETH, paraswapLiquiditySwapAdapter } = testEnv;
|
|
const user = users[0].signer;
|
|
const userAddress = users[0].address;
|
|
|
|
const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
|
|
|
|
const daiPrice = await oracle.getAssetPrice(dai.address);
|
|
const expectedDaiAmount = await convertToCurrencyDecimals(
|
|
dai.address,
|
|
new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
|
|
);
|
|
|
|
await mockAugustus.expectSwap(weth.address, dai.address, amountWETHtoSwap, amountWETHtoSwap, expectedDaiAmount);
|
|
|
|
// User will swap liquidity aEth to aDai
|
|
const userAEthBalanceBefore = await aWETH.balanceOf(userAddress);
|
|
|
|
const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID;
|
|
const deadline = MAX_UINT_AMOUNT;
|
|
const nonce = (await aWETH._nonces(userAddress)).toNumber();
|
|
const msgParams = buildPermitParams(
|
|
chainId,
|
|
aWETH.address,
|
|
'1',
|
|
await aWETH.name(),
|
|
userAddress,
|
|
paraswapLiquiditySwapAdapter.address,
|
|
nonce,
|
|
deadline,
|
|
amountWETHtoSwap.toString()
|
|
);
|
|
|
|
const ownerPrivateKey = require('../test-wallets.js').accounts[1].secretKey;
|
|
if (!ownerPrivateKey) {
|
|
throw new Error('INVALID_OWNER_PK');
|
|
}
|
|
|
|
const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams);
|
|
|
|
const mockAugustusCalldata = mockAugustus.interface.encodeFunctionData(
|
|
'swap',
|
|
[weth.address, dai.address, amountWETHtoSwap, expectedDaiAmount]
|
|
);
|
|
|
|
await expect(
|
|
paraswapLiquiditySwapAdapter.connect(user).swapAndDeposit(
|
|
weth.address,
|
|
dai.address,
|
|
amountWETHtoSwap,
|
|
expectedDaiAmount,
|
|
0,
|
|
mockAugustusCalldata,
|
|
mockAugustus.address,
|
|
{
|
|
amount: amountWETHtoSwap,
|
|
deadline,
|
|
v,
|
|
r,
|
|
s,
|
|
}
|
|
)
|
|
)
|
|
.to.emit(paraswapLiquiditySwapAdapter, 'Swapped')
|
|
.withArgs(weth.address, dai.address, amountWETHtoSwap, expectedDaiAmount);
|
|
|
|
const adapterWethBalance = await weth.balanceOf(paraswapLiquiditySwapAdapter.address);
|
|
const adapterDaiBalance = await dai.balanceOf(paraswapLiquiditySwapAdapter.address);
|
|
const userADaiBalance = await aDai.balanceOf(userAddress);
|
|
const userAEthBalance = await aWETH.balanceOf(userAddress);
|
|
|
|
expect(adapterWethBalance).to.be.eq(Zero);
|
|
expect(adapterDaiBalance).to.be.eq(Zero);
|
|
expect(userADaiBalance).to.be.eq(expectedDaiAmount);
|
|
expect(userAEthBalance).to.be.gt(userAEthBalanceBefore.sub(amountWETHtoSwap));
|
|
expect(userAEthBalance).to.be.lt(userAEthBalanceBefore.mul(10001).div(10000).sub(amountWETHtoSwap));
|
|
});
|
|
|
|
it('should correctly swap all the balance when using a bigger amount', async () => {
|
|
const { users, weth, oracle, dai, aDai, aWETH, paraswapLiquiditySwapAdapter } = testEnv;
|
|
const user = users[0].signer;
|
|
const userAddress = users[0].address;
|
|
|
|
const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
|
|
|
|
const daiPrice = await oracle.getAssetPrice(dai.address);
|
|
const expectedDaiAmount = await convertToCurrencyDecimals(
|
|
dai.address,
|
|
new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
|
|
);
|
|
|
|
await mockAugustus.expectSwap(weth.address, dai.address, amountWETHtoSwap.add(1), amountWETHtoSwap.mul(10001).div(10000), expectedDaiAmount);
|
|
|
|
// Remove other balance
|
|
await aWETH.connect(user).transfer(users[1].address, parseEther('90'));
|
|
|
|
// User will swap liquidity aEth to aDai
|
|
const bigAmountToSwap = parseEther('11');
|
|
await aWETH.connect(user).approve(paraswapLiquiditySwapAdapter.address, bigAmountToSwap);
|
|
|
|
const mockAugustusCalldata = mockAugustus.interface.encodeFunctionData(
|
|
'swap',
|
|
[weth.address, dai.address, bigAmountToSwap, expectedDaiAmount]
|
|
);
|
|
|
|
await expect(
|
|
paraswapLiquiditySwapAdapter.connect(user).swapAndDeposit(
|
|
weth.address,
|
|
dai.address,
|
|
bigAmountToSwap,
|
|
expectedDaiAmount,
|
|
4 + 2*32,
|
|
mockAugustusCalldata,
|
|
mockAugustus.address,
|
|
{
|
|
amount: 0,
|
|
deadline: 0,
|
|
v: 0,
|
|
r: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
s: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
}
|
|
)
|
|
).to.emit(paraswapLiquiditySwapAdapter, 'Swapped');
|
|
|
|
const adapterWethBalance = await weth.balanceOf(paraswapLiquiditySwapAdapter.address);
|
|
const adapterDaiBalance = await dai.balanceOf(paraswapLiquiditySwapAdapter.address);
|
|
const userADaiBalance = await aDai.balanceOf(userAddress);
|
|
const userAEthBalance = await aWETH.balanceOf(userAddress);
|
|
|
|
expect(adapterWethBalance).to.be.eq(Zero);
|
|
expect(adapterDaiBalance).to.be.eq(Zero);
|
|
expect(userADaiBalance).to.be.eq(expectedDaiAmount);
|
|
expect(userAEthBalance).to.be.eq(Zero);
|
|
});
|
|
|
|
it('should correctly swap all the balance when using permit', async () => {
|
|
const { users, weth, oracle, dai, aDai, aWETH, paraswapLiquiditySwapAdapter } = testEnv;
|
|
const user = users[0].signer;
|
|
const userAddress = users[0].address;
|
|
|
|
const amountWETHtoSwap = await convertToCurrencyDecimals(weth.address, '10');
|
|
|
|
const daiPrice = await oracle.getAssetPrice(dai.address);
|
|
const expectedDaiAmount = await convertToCurrencyDecimals(
|
|
dai.address,
|
|
new BigNumber(amountWETHtoSwap.toString()).div(daiPrice.toString()).toFixed(0)
|
|
);
|
|
|
|
await mockAugustus.expectSwap(weth.address, dai.address, amountWETHtoSwap.add(1), amountWETHtoSwap.mul(10001).div(10000), expectedDaiAmount);
|
|
|
|
// Remove other balance
|
|
await aWETH.connect(user).transfer(users[1].address, parseEther('90'));
|
|
|
|
// User will swap liquidity aEth to aDai
|
|
const bigAmountToSwap = parseEther('11');
|
|
|
|
const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID;
|
|
const deadline = MAX_UINT_AMOUNT;
|
|
const nonce = (await aWETH._nonces(userAddress)).toNumber();
|
|
const msgParams = buildPermitParams(
|
|
chainId,
|
|
aWETH.address,
|
|
'1',
|
|
await aWETH.name(),
|
|
userAddress,
|
|
paraswapLiquiditySwapAdapter.address,
|
|
nonce,
|
|
deadline,
|
|
bigAmountToSwap.toString()
|
|
);
|
|
|
|
const ownerPrivateKey = require('../test-wallets.js').accounts[1].secretKey;
|
|
if (!ownerPrivateKey) {
|
|
throw new Error('INVALID_OWNER_PK');
|
|
}
|
|
|
|
const { v, r, s } = getSignatureFromTypedData(ownerPrivateKey, msgParams);
|
|
|
|
const mockAugustusCalldata = mockAugustus.interface.encodeFunctionData(
|
|
'swap',
|
|
[weth.address, dai.address, bigAmountToSwap, expectedDaiAmount]
|
|
);
|
|
|
|
await expect(
|
|
paraswapLiquiditySwapAdapter.connect(user).swapAndDeposit(
|
|
weth.address,
|
|
dai.address,
|
|
bigAmountToSwap,
|
|
expectedDaiAmount,
|
|
4 + 2*32,
|
|
mockAugustusCalldata,
|
|
mockAugustus.address,
|
|
{
|
|
amount: bigAmountToSwap,
|
|
deadline,
|
|
v,
|
|
r,
|
|
s,
|
|
}
|
|
)
|
|
).to.emit(paraswapLiquiditySwapAdapter, 'Swapped');
|
|
|
|
const adapterWethBalance = await weth.balanceOf(paraswapLiquiditySwapAdapter.address);
|
|
const adapterDaiBalance = await dai.balanceOf(paraswapLiquiditySwapAdapter.address);
|
|
const userADaiBalance = await aDai.balanceOf(userAddress);
|
|
const userAEthBalance = await aWETH.balanceOf(userAddress);
|
|
|
|
expect(adapterWethBalance).to.be.eq(Zero);
|
|
expect(adapterDaiBalance).to.be.eq(Zero);
|
|
expect(userADaiBalance).to.be.eq(expectedDaiAmount);
|
|
expect(userAEthBalance).to.be.eq(Zero);
|
|
});
|
|
});
|
|
});
|
|
});
|