* @notice this function is an end of deposit flow.
* @dev should update all necessary global state variables
*
* @param depositId `depositId` of mint operation
* @param amount actual deposit amount. if `_isLongOneLeverage` is `true`, amount of `indexToken`, or amount of `collateralToken`
*/
function _mint(uint256 depositId, uint256 amount, bool refundFee, MarketPrices memory prices) internal {
uint256 _shares;
if (totalShares == 0) {
_shares = depositInfo[depositId].amount * 1e8;
} else {
uint256 totalAmountBefore;
if (positionIsClosed == false && _isLongOneLeverage(beenLong)) {
totalAmountBefore = IERC20(indexToken).balanceOf(address(this)) - amount;
} else {
totalAmountBefore = _totalAmount(prices) - amount;
}
if (totalAmountBefore == 0) totalAmountBefore = 1;
_shares = amount * totalShares / totalAmountBefore;
}
depositInfo[depositId].shares = _shares;
totalShares = totalShares + _shares;
...
}
totalAmountBefore = IERC20(indexToken).balanceOf(address(this)) - amount;
totalAmountBefore = totalAmountBefore == 0 ? 1 : totalAmountBefore;
_shares = amount * totalShares / totalAmountBefore;
indexToken = ETH, 18 decimals
collateralToken = USDC, 6 decimals
collateralAmount = 1000e6
shares = collateralAmount * 1e8 = 1000e6 * 1e8 = 1e17
totalShares = 1e17
indexTokenBalance = 1e18
indexTokenAmount = 1e18
totalShares = 1e17
totalAmountBefore = 1e18 - 1e18 = 0 == 0 ? 1 : 0 = 1
shares = 1e18 * 1e17 / 1 = 1e35
Shares minted in second deposit is much larger than in first.
function test_WrongDecimalsDeposit() external {
address keeper = PerpetualVault(vault).keeper();
VaultReader vaultReader = VaultReader(address(PerpetualVault(vault).vaultReader()));
IERC20 collateralToken = PerpetualVault(vault).collateralToken();
IERC20 indexToken = IERC20(PerpetualVault(vault).indexToken());
address alice = makeAddr("alice");
uint256 amount = 10000e6;
deal(address(collateralToken), alice, amount * 2);
uint256 correctSharesAmount = 1e18;
uint256 executionFee = PerpetualVault(vault).getExecutionGasLimit(true);
vm.startPrank(alice);
collateralToken.approve(vault, amount * 2);
PerpetualVault(vault).deposit{value: executionFee * tx.gasprice}(amount);
(, uint256 shares0,,,,) = PerpetualVault(vault).depositInfo(1);
assertEq(shares0, correctSharesAmount);
vm.stopPrank();
MarketPrices memory prices = mockData.getMarketPrices();
bytes[] memory data = new bytes[](1);
data[0] = abi.encode(3380000000000000);
vm.prank(keeper);
PerpetualVault(vault).run(true, false, prices, data);
PerpetualVault.FLOW flow = PerpetualVault(vault).flow();
assertEq(uint8(flow), 2);
assertEq(PerpetualVault(vault).positionIsClosed(), true);
(PerpetualVault.NextActionSelector selector, ) = PerpetualVault(vault).nextAction();
assertEq(uint8(selector), 0);
GmxOrderExecuted(true);
bytes32 curPositionKey = PerpetualVault(vault).curPositionKey();
assertTrue(curPositionKey != bytes32(0));
vm.stopPrank();
PerpetualVault(vault).setVaultState(
PerpetualVault.FLOW.NONE,
uint256(0),
true,
curPositionKey,
false,
false,
PerpetualVault.Action(
PerpetualVault.NextActionSelector.NO_ACTION,
abi.encode(true)
)
);
vm.deal(alice, 1 ether);
vm.startPrank(alice);
uint256 executionFee2 = PerpetualVault(vault).getExecutionGasLimit(true);
PerpetualVault(vault).deposit{value: executionFee2 * tx.gasprice }(amount);
vm.stopPrank();
bytes[] memory metadata = new bytes[](1);
metadata[0] = abi.encode(PROTOCOL.DEX, mockData.getParaSwapData(vault));
vm.warp(1);
PerpetualVault(vault).setVaultState(
PerpetualVault.FLOW.DEPOSIT,
uint256(0),
true,
curPositionKey,
false,
false,
PerpetualVault.Action(
PerpetualVault.NextActionSelector.INCREASE_ACTION,
abi.encode(true)
)
);
vm.prank(keeper);
PerpetualVault(vault).runNextAction(prices, metadata);
vm.stopPrank();
(, uint256 shares1,,,,) = PerpetualVault(vault).depositInfo(2);
console.log("Shares by collateral deposit: ", shares0);
console.log("Shares by index deposit: ", shares1);
}
Shares minted through index token in the first deposit will be much larger than it should be.