BriVault

First Flight #52
Beginner FriendlySolidity
100 EXP
View results
Submission Details
Severity: high
Valid

M01. Inconsistent Receiver and Share Ownership in deposit() Function

Root + Impact

Description

  • Under normal conditions, when a user calls deposit, the vault should record the staker’s address and mint shares to the same address, ensuring accounting consistency between who deposited funds and who owns the shares.

  • In the current implementation, the deposit function records the staked amount under the receiver address but mints ERC20 vault shares to msg.sender. This creates a mismatch between who owns shares and who is credited as having staked assets, which can lead to theft, locked funds, or incorrect accounting.

function deposit(uint256 assets, address receiver) public override returns (uint256) {
...
uint256 stakeAsset = assets - fee;
@> stakedAsset[receiver] = stakeAsset; // Records stake under `receiver`
uint256 participantShares = _convertToShares(stakeAsset);
IERC20(asset()).safeTransferFrom(msg.sender, participationFeeAddress, fee);
IERC20(asset()).safeTransferFrom(msg.sender, address(this), stakeAsset);
@> _mint(msg.sender, participantShares); // Mints shares to `msg.sender`, not `receiver`
emit deposited(receiver, stakeAsset);
return participantShares;
}

Risk

Likelihood:

  • Occurs whenever deposit is called with a receiver different from msg.sender, which is supported by the function signature and not restricted anywhere.

  • Users or external integrators can easily invoke this pattern when automating deposits on behalf of others (e.g., front-end UI or staking manager).

Impact:

  • The payer (msg.sender) receives the vault shares and thus can later withdraw or transfer them, while the credited receiver is shown as staked but cannot withdraw.

  • This mismatch can lead to user funds being locked, or malicious actors minting shares for themselves while crediting another user’s stake record.

Proof of Concept

function testDepositMismatch() public {
// user1 deposits on behalf of user2
vm.startPrank(user1);
mockToken.approve(address(briVault), 10 ether);
briVault.deposit(10 ether, user2);
vm.stopPrank();
// user2 appears to have staked funds
assertEq(briVault.stakedAsset(user2), 10 ether);
// but user1 holds the minted shares and can withdraw later
assertGt(briVault.balanceOf(user1), 0);
assertEq(briVault.balanceOf(user2), 0);
}

Explanation:
user1 pays and the vault records user2 as staked, but the minted ERC20 shares are given to user1. user1 can later withdraw from the vault, draining user2’s stake, while user2 cannot access their supposed deposit.

Recommended Mitigation

Ensure the same address both stakes and receives the shares. Either restrict deposits to self-only or correctly mint to the receiver.

- _mint(msg.sender, participantShares);
+ _mint(receiver, participantShares);
Updates

Appeal created

bryanconquer Lead Judge 19 days ago
Submission Judgement Published
Validated
Assigned finding tags:

Shares Minted to msg.sender Instead of Specified Receiver

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!