Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 15 additions & 21 deletions contracts/vault/libraries/MinterLogic.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ library MinterLogic {
/// @dev Share precision
uint256 constant SHARE_PRECISION = 1e33;

/// @dev Minimum asset price
uint256 constant MIN_ASSET_PRICE = 0.995e8;

/// @notice Calculate the amount out from a swap including fees
/// @param $ Storage pointer
/// @param params Parameters for a swap
Expand Down Expand Up @@ -74,38 +77,29 @@ library MinterLogic {
view
returns (uint256 amount, uint256 newRatio)
{
(uint256 assetPrice,) = IOracle(_oracle).getPrice(params.asset);
(uint256 capPrice,) = IOracle(_oracle).getPrice(address(this));

uint256 assetDecimalsPow = 10 ** IERC20Metadata(params.asset).decimals();
uint256 capDecimalsPow = 10 ** IERC20Metadata(address(this)).decimals();

uint256 capSupply = IERC20(address(this)).totalSupply();
uint256 capValue = capSupply * capPrice / capDecimalsPow;
uint256 allocationValue = IVault(address(this)).totalSupplies(params.asset) * assetPrice / assetDecimalsPow;
uint256 allocationValue = IVault(address(this)).totalSupplies(params.asset) * capDecimalsPow / assetDecimalsPow;

uint256 assetValue;
if (params.mint) {
assetValue = params.amount * assetPrice / assetDecimalsPow;
(uint256 assetPrice,) = IOracle(_oracle).getPrice(params.asset);
if (assetPrice < MIN_ASSET_PRICE) {
amount = 0;
} else {
amount = params.amount * capDecimalsPow / assetDecimalsPow;
}
if (capSupply == 0) {
newRatio = 0;
amount = assetValue * capDecimalsPow / assetPrice;
} else {
newRatio = (allocationValue + assetValue) * RAY_PRECISION / (capValue + assetValue);
amount = assetValue * capDecimalsPow / capPrice;
newRatio = RAY_PRECISION * (allocationValue + amount) / (capSupply + amount);
}
} else {
assetValue = params.amount * capPrice / capDecimalsPow;
if (params.amount == capSupply) {
newRatio = RAY_PRECISION;
amount = assetValue * assetDecimalsPow / assetPrice;
amount = params.amount * assetDecimalsPow / capDecimalsPow;
if (params.amount >= allocationValue || params.amount >= capSupply) {
newRatio = 0;
} else {
if (allocationValue < assetValue || capValue <= assetValue) {
newRatio = 0;
} else {
newRatio = (allocationValue - assetValue) * RAY_PRECISION / (capValue - assetValue);
}
amount = assetValue * assetDecimalsPow / assetPrice;
newRatio = RAY_PRECISION * (allocationValue - params.amount) / (capSupply - params.amount);
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions snapshots/Vault.gas.t.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"simple_burn": "253210",
"simple_mint": "250005"
"simple_burn": "111917",
"simple_mint": "142649"
}
8 changes: 4 additions & 4 deletions test/scenario/Scenario.basic.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -92,16 +92,16 @@ contract ScenarioBasicTest is CapIntegrationFixture {
cUSD.mint(address(usdt), 2000e6, 3000e18, alice, block.timestamp + 1 hours);
vm.expectRevert();
/// Time
cUSD.mint(address(usdt), 2000e6, 1990e18, alice, block.timestamp - 1);
cUSD.mint(address(usdt), 2000e6, 1990e18, alice, block.timestamp + 1 hours);
assertGt(cUSD.balanceOf(alice), 1990e18);
cUSD.mint(address(usdt), 2000e6, 1989e18, alice, block.timestamp - 1);
cUSD.mint(address(usdt), 2000e6, 1989e18, alice, block.timestamp + 1 hours);
assertGt(cUSD.balanceOf(alice), 1989e18);

vm.stopPrank();

vm.startPrank(bob);

usdc.approve(address(cUSD), 10000e6);
cUSD.mint(address(usdc), 2000e6, 1990e6, bob, block.timestamp + 1 hours);
cUSD.mint(address(usdc), 2000e6, 1989e6, bob, block.timestamp + 1 hours);

assertLt(cUSD.balanceOf(bob), 2000e18);

Expand Down
16 changes: 15 additions & 1 deletion test/vault/libraries/MinterLogic.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,21 @@ contract MinterLogicTest is Test {

uint256 amount = vault.minter_getAmountOut(params);

assertApproxEqAbs(amount, 200e18, 2, "Amount should account for price difference");
assertApproxEqAbs(amount, 100e18, 2, "Amount should not account for price difference");
}

function test_getAmountOut_zero_when_oracle_below_min_mint_price() public {
vault.mockMinimumTotalSupply(1000e18);
vault.mockTotalSupplies(address(asset), 1000e18);
vault.mockTotalSupplies(address(vault), 1000e18);

oracle.setPrice(address(asset), 0.994e8);

IMinter.AmountOutParams memory params =
IMinter.AmountOutParams({ asset: address(asset), amount: 100e18, mint: true, user: msg.sender });

uint256 amount = vault.minter_getAmountOut(params);
assertEq(amount, 0, "Below MIN_ASSET_PRICE mint quote is zero so mint reverts on InvalidAmount");
}

function test_getAmountOut_zeroAmount() public {
Expand Down