Some ERC20 tokens do not work when changing the allowance from an existing non-zero allowance value
Can liquidate more than once (different Vaults) for the same token. It will lead to bad debt
const { expect } = require("chai");
const { ethers, network } = require("hardhat");
const { BigNumber } = ethers;
const { mockTokenManager, DEFAULT_EUR_USD_PRICE, DEFAULT_ETH_USD_PRICE, DEFAULT_WBTC_USD_PRICE, DEFAULT_USDC_USD_PRICE, DEFAULT_COLLATERAL_RATE, HUNDRED_PC, TOKEN_ID, rewardAmountForAsset, fastForward, DAY, POOL_FEE_PERCENTAGE, fullyUpgradedSmartVaultManager, PROTOCOL_FEE_RATE } = require("./common");
describe('LiquidationPoolManager', async () => {
let LiquidationPoolManager, LiquidationPoolManagerContract, LiquidationPool, SmartVaultManager, TokenManager,
TST, EUROs, WBTC, USDC, holder1, holder2, holder3, holder4, holder5, Protocol, ERC20MockFactory;
beforeEach(async () => {
[holder1, holder2, holder3, holder4, holder5, Protocol] = await ethers.getSigners();
ERC20MockFactory = await ethers.getContractFactory('ERC20Mock');
TST = await ERC20MockFactory.deploy('The Standard Token', 'TST', 18);
EUROs = await (await ethers.getContractFactory('EUROsMock')).deploy();
({ TokenManager, WBTC, USDC } = await mockTokenManager());
SmartVaultManager = await (await ethers.getContractFactory('MockSmartVaultManager')).deploy(DEFAULT_COLLATERAL_RATE, TokenManager.address);
const EurUsd = await (await ethers.getContractFactory('ChainlinkMock')).deploy('EUR/USD');
await EurUsd.setPrice(DEFAULT_EUR_USD_PRICE);
LiquidationPoolManagerContract = await ethers.getContractFactory('LiquidationPoolManager');
LiquidationPoolManager = await LiquidationPoolManagerContract.deploy(
TST.address, EUROs.address, SmartVaultManager.address, EurUsd.address, Protocol.address, POOL_FEE_PERCENTAGE
);
LiquidationPool = await ethers.getContractAt('LiquidationPool', await LiquidationPoolManager.pool());
await EUROs.grantRole(await EUROs.BURNER_ROLE(), LiquidationPool.address);
});
afterEach(async () => {
await network.provider.send("hardhat_reset")
});
describe('runLiquidation', async () => {
it('forwards fees and rewards to protocol if there is no tst staked in pool', async () => {
const fees = ethers.utils.parseEther('1000');
const USDT = await prepareUSDT();
uint256 _portion = asset.amount * _positionStake / stakeTotal;
console.log(asset.amount); console.log(_portion);
Output:
100000000
99900099
100000000
99900
*/
await stake(holder1, ethers.utils.parseEther('1000'));
await stake(holder2, ethers.utils.parseEther('1'));
await EUROs.mint(LiquidationPoolManager.address, fees);
console.log(
'allowance before liquidation',
await USDT.allowance(LiquidationPoolManager.address, LiquidationPool.address)
);
await LiquidationPoolManager.runLiquidation(TOKEN_ID);
const allowanceAfter = await USDT
.allowance(LiquidationPoolManager.address, LiquidationPool.address);
console.log( 'allowance after liquidation', allowanceAfter );
expect(allowanceAfter).to.equal(BigNumber.from('1'));
await USDT.mint(SmartVaultManager.address, BigNumber.from(100000000));
try {
await LiquidationPoolManager.runLiquidation(TOKEN_ID);
expect.fail('Transaction should have failed but did not');
} catch (error) {
console.log(error.message);
expect(error.message).to.include(
'Failed in USDTApprovalMock',
'Transaction failed for an unexpected reason'
);
}
});
async function stake(holder, stake) {
await EUROs.mint(holder.address, stake);
await EUROs.connect(holder).approve(LiquidationPool.address, stake);
await TST.mint(holder.address, stake);
await TST.connect(holder).approve(LiquidationPool.address, stake);
await LiquidationPool.connect(holder).increasePosition(stake, stake);
fastForward(DAY);
}
async function prepareUSDT() {
const usdtCollateral = BigNumber.from(100000000);
const UsdtFactory = await ethers.getContractFactory('USDTApprovalMock');
const USDT = await UsdtFactory.deploy('USDT', 'USDT');
const UsdtUsd = await (await ethers.getContractFactory('ChainlinkMock')).deploy('USDT/USD');
await UsdtUsd.setPrice(DEFAULT_USDC_USD_PRICE);
await TokenManager.addAcceptedToken(USDT.address, UsdtUsd.address);
await USDT.mint(SmartVaultManager.address, usdtCollateral);
return USDT;
}
});
});