function deposit(uint256 assets, address receiver) public override returns (uint256) {
require(receiver != address(0));
if (block.timestamp >= eventStartDate) {
revert eventStarted();
}
uint256 fee = _getParticipationFee(assets);
if (minimumAmount + fee > assets) {
revert lowFeeAndAmount();
}
uint256 stakeAsset = assets - fee;
stakedAsset[receiver] = stakeAsset;
@> uint256 participantShares = _convertToShares(stakeAsset);
IERC20(asset()).safeTransferFrom(msg.sender, participationFeeAddress, fee);
IERC20(asset()).safeTransferFrom(msg.sender, address(this), stakeAsset);
@> _mint(msg.sender, participantShares);
emit deposited(receiver, stakeAsset);
return participantShares;
}
function test_wrongOrderOfSharesMinting_possibleInflationAttack() public {
uint256 depositAmount = 5 ether;
uint256 BASE = 10000;
uint256 feeOnDeposit = (depositAmount * briVault.participationFeeBsp()) / BASE;
uint256 stackedAsset = depositAmount - feeOnDeposit;
vm.startPrank(user1);
mockToken.approve(address(briVault), depositAmount);
uint256 vaultTotalSupplyBeforeDeposit1 = briVault.totalSupply();
briVault.deposit(depositAmount, user1);
vm.stopPrank();
assertEq(briVault.balanceOf(user1), stackedAsset);
vm.startPrank(user2);
mockToken.approve(address(briVault), depositAmount);
uint256 vaultTotalSupplyBeforeDeposit2 = briVault.totalSupply();
uint256 vaultBalanceBeforeDeposit2 = mockToken.balanceOf(address(briVault));
briVault.deposit(depositAmount, user2);
vm.stopPrank();
uint256 vaultBalanceAfterDeposit2 = mockToken.balanceOf(address(briVault));
uint256 calculatedSharesToBeMintedAfterDeposit2 =
Math.mulDiv(stackedAsset, vaultTotalSupplyBeforeDeposit2, vaultBalanceAfterDeposit2);
uint256 actuallyMintedSharesForUser2 = briVault.balanceOf(user2);
assertGt(actuallyMintedSharesForUser2, calculatedSharesToBeMintedAfterDeposit2);
uint256 calculatedSharesUsingOldVaultBalance2 =
Math.mulDiv(stackedAsset, vaultTotalSupplyBeforeDeposit2, vaultBalanceBeforeDeposit2);
assertEq(actuallyMintedSharesForUser2, calculatedSharesUsingOldVaultBalance2);
vm.startPrank(user3);
mockToken.approve(address(briVault), depositAmount);
uint256 vaultTotalSupplyBeforeDeposit3 = briVault.totalSupply();
uint256 vaultBalanceBeforeDeposit3 = mockToken.balanceOf(address(briVault));
briVault.deposit(depositAmount, user3);
vm.stopPrank();
uint256 vaultBalanceAfterDeposit3 = mockToken.balanceOf(address(briVault));
uint256 calculatedSharesToBeMintedAfterDeposit3 =
Math.mulDiv(stackedAsset, vaultTotalSupplyBeforeDeposit3, vaultBalanceAfterDeposit3);
uint256 actuallyMintedSharesForUser3 = briVault.balanceOf(user3);
assertGt(actuallyMintedSharesForUser3, calculatedSharesToBeMintedAfterDeposit3);
uint256 calculatedSharesUsingOldVaultBalance3 =
Math.mulDiv(stackedAsset, vaultTotalSupplyBeforeDeposit3, vaultBalanceBeforeDeposit3);
assertEq(actuallyMintedSharesForUser3, calculatedSharesUsingOldVaultBalance3);
}
function deposit(uint256 assets, address receiver) public override returns (uint256) {
require(receiver != address(0));
if (block.timestamp >= eventStartDate) {
revert eventStarted();
}
uint256 fee = _getParticipationFee(assets);
// charge on a percentage basis points
if (minimumAmount + fee > assets) {
revert lowFeeAndAmount();
}
uint256 stakeAsset = assets - fee;
stakedAsset[receiver] = stakeAsset;
- uint256 participantShares = _convertToShares(stakeAsset);
IERC20(asset()).safeTransferFrom(msg.sender, participationFeeAddress, fee);
IERC20(asset()).safeTransferFrom(msg.sender, address(this), stakeAsset);
+ uint256 participantShares = _convertToShares(stakeAsset);
_mint(msg.sender, participantShares);
emit deposited(receiver, stakeAsset);
return participantShares;
}