stakedAsset in deposit() only records the last stakeAsset made - a user is not able to get all their stakeAssets out with cancelParticipation() if they deposited more than once
Description
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;
}
Risk
Likelihood:
Impact:
Proof of Concept
Place this in test/briVault.t.sol:
function test_cancelAfterMultipleDeposits () public {
vm.startPrank(user1);
console.log("user1 original MTK balance");
console.log(mockToken.balanceOf(address(user1)));
mockToken.approve(address(briVault), 5 ether);
briVault.deposit(5 ether, user1);
mockToken.approve(address(briVault), 5 ether);
briVault.deposit(5 ether, user1);
briVault.cancelParticipation();
vm.stopPrank();
assertEq(briVault.stakedAsset(user1), 0 ether);
console.log("user1 after cancelParticipation() MTK balance");
console.log(mockToken.balanceOf(address(user1)));
}
Run with
forge test -vvv --match-test test_cancelAfterMultipleDeposits
Sample output
Ran 1 test for test/briVault.t.sol:BriVaultTest
[PASS] test_cancelAfterMultipleDeposits() (gas: 194867)
Logs:
user1 original MTK balance
20000000000000000000
user1 after cancelParticipation() MTK balance
14925000000000000000
Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 3.44ms (617.46µs CPU time)
Ran 1 test suite in 11.46ms (3.44ms CPU time): 1 tests passed, 0 failed, 0 skipped (1 total tests)
Recommended Mitigation
In src/briVault.solmake stakedAsset record the total sum of stakeAsset for each receiver.
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;
}