BriVault::deposit, function doesn't increment user stakedAsset mappings after multiple deposits, resulting in an accounting error
Description
-
A user stakedAsset is a mapping that tracks user , this should increment user asset after depositing
-
but the function doesnt increment that mapping
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);
Risk: High, user actual asset inside the vault become mismatched with the accounting
Likelihood:
Impact:
Proof of Concept
add this to your test suite:
the correct behaviour was that user stakedAsset should increment, but inside this test suite the mapping doesnt increment, it just rewrites the data
function test_multipleDepositBadAccounting() public {
vm.prank(owner);
briVault.setCountry(countries);
uint256 deposit = 0.00023 ether;
vm.startPrank(user1);
mockToken.approve(address(briVault), deposit * 2);
briVault.deposit(deposit, user1);
uint256 user1stakedAsset = briVault.stakedAsset(user1);
briVault.deposit(deposit, user1);
vm.stopPrank();
uint256 user1stakedAssetAfter = briVault.stakedAsset(user1);
assertEq(user1stakedAsset, user1stakedAssetAfter);
}
Recommended Mitigation
by adding a + sign we can mitigate this issue.
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;
- 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;
}