function runLiquidation(uint256 _tokenId) external {
ISmartVaultManager manager = ISmartVaultManager(smartVaultManager);
manager.liquidateVault(_tokenId);
distributeFees();
ITokenManager.Token[] memory tokens = ITokenManager(manager.tokenManager()).getAcceptedTokens();
ILiquidationPoolManager.Asset[] memory assets = new ILiquidationPoolManager.Asset[](tokens.length);
uint256 ethBalance;
>> for (uint256 i = 0; i < tokens.length; i++) {
ITokenManager.Token memory token = tokens[i];
if (token.addr == address(0)) {
ethBalance = address(this).balance;
if (ethBalance > 0) assets[i] = ILiquidationPoolManager.Asset(token, ethBalance);
} else {
IERC20 ierc20 = IERC20(token.addr);
uint256 erc20balance = ierc20.balanceOf(address(this));
if (erc20balance > 0) {
assets[i] = ILiquidationPoolManager.Asset(token, erc20balance);
ierc20.approve(pool, erc20balance);
}
}
}
>> LiquidationPool(pool).distributeAssets{value: ethBalance}(
assets, manager.collateralRate(), manager.HUNDRED_PC()
);
forwardRemainingRewards(tokens);
}
function distributeAssets(
ILiquidationPoolManager.Asset[] memory _assets,
uint256 _collateralRate,
uint256 _hundredPC
) external payable {
consolidatePendingStakes();
(, int256 priceEurUsd,,,) = Chainlink.AggregatorV3Interface(eurUsd).latestRoundData();
>> uint256 stakeTotal = getStakeTotal();
uint256 burnEuros;
uint256 nativePurchased;
>> for (uint256 j = 0; j < holders.length; j++) {
Position memory _position = positions[holders[j]];
uint256 _positionStake = stake(_position);
if (_positionStake > 0) {
for (uint256 i = 0; i < _assets.length; i++) {
}
positions[holders[j]] = _position;
}
if (burnEuros > 0) IEUROs(EUROs).burn(address(this), burnEuros);
returnUnpurchasedNative(_assets, nativePurchased);
}
pragma solidity ^0.8.17;
import "forge-std/console.sol";
import "forge-std/Test.sol";
import "../../contracts/utils/SmartVaultDeployerV3.sol";
import "../../contracts/SmartVaultManagerV5.sol";
import "../../contracts/utils/EUROsMock.sol";
import "../../contracts/utils/SmartVaultIndex.sol";
import "../../contracts/LiquidationPoolManager.sol";
import "../../contracts/LiquidationPool.sol";
import "../../contracts/SmartVaultV3.sol";
import "../../contracts/utils/ERC20Mock.sol";
import "../../contracts/utils/TokenManagerMock.sol";
import "../../contracts/utils/ChainlinkMock.sol";
contract setup is Test {
ChainlinkMock clmock;
ChainlinkMock clmock1;
TokenManagerMock tokenmanager;
SmartVaultDeployerV3 deployer;
SmartVaultManagerV5 manager;
SmartVaultIndex vaultIndex;
EUROsMock euro;
LiquidationPoolManager poolmanager;
LiquidationPool pool;
ERC20Mock tst;
ChainlinkMock clmock2;
ERC20Mock token;
address bob = makeAddr("bob");
address alice = makeAddr("alice");
function onERC721Received(address ,address ,uint ,bytes memory ) public pure returns (bytes4 retval){
return this.onERC721Received.selector;
}
receive() external payable {}
function setUp() public virtual {
skip(3 days);
clmock = new ChainlinkMock("native price feed");
clmock.setPrice(160000000000);
clmock1 = new ChainlinkMock("euro price feed");
clmock1.setPrice(150000000);
tokenmanager = new TokenManagerMock(bytes32("native"),address (clmock));
clmock2 = new ChainlinkMock("random token price feed");
token = new ERC20Mock("token","tk",18);
token.mint(bob,10000 ether);
clmock2.setPrice(100000000);
tokenmanager.addAcceptedToken(address(token),address(clmock2));
manager = new SmartVaultManagerV5();
vaultIndex = new SmartVaultIndex();
vaultIndex.setVaultManager(address(manager));
euro = new EUROsMock();
tst = new ERC20Mock("test tst","tst", 18);
deployer = new SmartVaultDeployerV3(bytes32("native"),address(clmock1));
manager.initialize(vaultIndex,address(euro),address(tokenmanager));
poolmanager = new LiquidationPoolManager(address(tst),address(euro),address(manager),address(clmock1), payable (address(this)),50000);
pool = LiquidationPool(poolmanager.pool());
manager.setSmartVaultDeployer(address(deployer));
euro.grantRole(euro.DEFAULT_ADMIN_ROLE(),address(manager));
manager.setLiquidatorAddress(address(poolmanager));
manager.setMintFeeRate(10000);
manager.setBurnFeeRate(5000);
manager.setSwapFeeRate(5000);
manager.setProtocolAddress(address(poolmanager));
vm.deal(address(this), 20 ether);
}
function test_runLiquidation() public {
(address vault,uint tokenId) = manager.mint();
(bool ok,) = vault.call{value: 2 ether}("");
require(ok);
SmartVaultV3(payable (vault)).mint(bob, 1600 ether);
clmock.setPrice(1600000000);
for (uint i;i< 1000;i++) {
address to = address(uint160(uint(keccak256(abi.encode(i)))));
tst.mint(to,i * 1 ether + 1);
vm.startPrank(to);
tst.approve(address(pool), tst.balanceOf(to));
pool.increasePosition(tst.balanceOf(to),0);
vm.stopPrank();
}
skip(3 days);
uint gasBefore = gasleft();
poolmanager.runLiquidation(tokenId);
uint gasConsumed = gasBefore - gasleft();
console.log("gas used for runing liquidation with one token and 1000 holders is :",gasConsumed);
console.log("number of holders ",pool.len());
}