https://github.com/Cyfrin/2023-12-the-standard/blob/91132936cb09ef9bf82f38ab1106346e2ad60f91/contracts/SmartVaultV3.sol#L127-L133
We minted €40. Used €80 collateral.
€120 collateral are not used, it should be allowed to withdraw it
const { ethers } = require('hardhat');
const { BigNumber } = ethers;
const { expect } = require('chai');
const { DEFAULT_ETH_USD_PRICE, DEFAULT_EUR_USD_PRICE, DEFAULT_COLLATERAL_RATE, PROTOCOL_FEE_RATE, getCollateralOf, ETH, getNFTMetadataContract, fullyUpgradedSmartVaultManager } = require('./common');
const { HUNDRED_PC } = require('./common');
let VaultManager, Vault, TokenManager, ClEthUsd, EUROs, SwapRouterMock, MockWeth, admin, user, otherUser, protocol;
describe('SmartVault', async () => {
beforeEach(async () => {
[ admin, user, otherUser, protocol ] = await ethers.getSigners();
ClEthUsd = await (await ethers.getContractFactory('ChainlinkMock')).deploy('ETH / USD');
await ClEthUsd.setPrice(DEFAULT_ETH_USD_PRICE);
const ClEurUsd = await (await ethers.getContractFactory('ChainlinkMock')).deploy('EUR / USD');
await ClEurUsd.setPrice(DEFAULT_EUR_USD_PRICE);
EUROs = await (await ethers.getContractFactory('EUROsMock')).deploy();
TokenManager = await (await ethers.getContractFactory('TokenManagerMock')).deploy(ETH, ClEthUsd.address);
const SmartVaultDeployer = await (await ethers.getContractFactory('SmartVaultDeployerV3')).deploy(ETH, ClEurUsd.address);
const SmartVaultIndex = await (await ethers.getContractFactory('SmartVaultIndex')).deploy();
const NFTMetadataGenerator = await (await getNFTMetadataContract()).deploy();
SwapRouterMock = await (await ethers.getContractFactory('SwapRouterMock')).deploy();
MockWeth = await (await ethers.getContractFactory('WETHMock')).deploy();
VaultManager = await fullyUpgradedSmartVaultManager(
BigNumber.from(200000),
PROTOCOL_FEE_RATE, EUROs.address, protocol.address,
protocol.address, TokenManager.address, SmartVaultDeployer.address,
SmartVaultIndex.address, NFTMetadataGenerator.address, MockWeth.address,
SwapRouterMock.address
);
await SmartVaultIndex.setVaultManager(VaultManager.address);
await EUROs.grantRole(await EUROs.DEFAULT_ADMIN_ROLE(), VaultManager.address);
await VaultManager.connect(user).mint();
const { status } = (await VaultManager.connect(user).vaults())[0];
const { vaultAddress } = status;
Vault = await ethers.getContractAt('SmartVaultV3', vaultAddress);
});
describe('adding collateral', async () => {
it('accepts native currency as collateral', async () => {
const hundredEur = BigNumber.from(10).pow(20);
const value = hundredEur.mul(2).mul(DEFAULT_EUR_USD_PRICE).div(DEFAULT_ETH_USD_PRICE);
await user.sendTransaction({to: Vault.address, value});
const statusBeforeMint = await parseStatus();
console.log('Nothing minted yet:');
await printStatus(statusBeforeMint);
await Vault.connect(user).mint(
user.address,
BigNumber.from(1)
);
const statusAfterMint1Wei = await parseStatus();
console.log('After 1 wei minted:');
await printStatus(statusAfterMint1Wei);
const remove = Vault.connect(user).removeCollateralNative(
value.div(2),
user.address,
);
await expect(remove).to.be.revertedWith('err-under-coll');
await Vault.connect(user).mint(
user.address,
hundredEur.mul(4).div(10)
);
const statusAfter40Percent = await parseStatus();
console.log('After ~40% minted:');
await printStatus(statusAfter40Percent);
const remove30Percent = Vault.connect(user).removeCollateralNative(
value.mul(30).div(100),
user.address,
);
await expect(remove30Percent).to.be.revertedWith('err-under-coll');
});
});
});
async function parseStatus() {
const { minted, maxMintable, totalCollateralValue } = await Vault.status();
const totalCollateralUsed = totalCollateralValue.mul(minted).div(maxMintable);
const totalCollateralUnused = totalCollateralValue.sub(totalCollateralUsed);
const PERCENT_MULTIPLIER = 1000;
const unusedInPercents = totalCollateralUnused
.mul(PERCENT_MULTIPLIER)
.div(totalCollateralValue)
.toNumber() / PERCENT_MULTIPLIER;
return { minted, maxMintable, totalCollateralValue, totalCollateralUsed, totalCollateralUnused, unusedInPercents };
}
async function printStatus({
minted, maxMintable, totalCollateralValue, totalCollateralUsed, totalCollateralUnused, unusedInPercents
}) {
console.log( {
minted: ethers.utils.formatEther(minted),
maxMintable: ethers.utils.formatEther(maxMintable),
totalCollateralValue: ethers.utils.formatEther(totalCollateralValue),
totalCollateralUsed: ethers.utils.formatEther(totalCollateralUsed),
totalCollateralUnused: ethers.utils.formatEther(totalCollateralUnused),
unusedInPercents: `${unusedInPercents*100}%`,
} );
}