Root: The deposit function mints ERC4626 shares to msg.sender while assigning the participation right (stakedAsset record) to the receiver address.
Impact: This fundamental accounting split makes it impossible for a user to complete the intended "deposit -> join -> withdraw" lifecycle correctly. It breaks the core application logic, leads to failed transactions and confusing states, and forces users to rely on unintended bypass mechanisms (standard ERC4626 functions) to recover funds, defeating the purpose of the tournament's rules.
The intended user flow of the protocol requires a participant to first deposit assets to receive shares, and then use their credited stake to join the tournament by selecting a team. A critical invariant for this to work is that the address holding the shares must be the same address credited with the stake.
The deposit function violates this invariant by allowing msg.sender and receiver to be different addresses. It correctly mints shares to the depositor (msg.sender) but incorrectly assigns the stake record—the prerequisite for joining the event—to the receiver.
This creates a broken state with the following consequences:
Depositor (msg.sender) Cannot Participate: The user who funded the deposit and holds the shares cannot call joinEvent because the contract does not recognize their stake (stakedAsset[msg.sender] is zero).
Receiver's Participation is Ineffective: The receiver can call joinEvent, but since they hold no shares (balanceOf(receiver) is zero), their participation is meaningless. They are registered as joining with zero contribution.
While funds are not permanently locked due to the presence of un-overridden ERC4626 withdraw and redeem functions, the primary application logic is unequivocally broken. Users are forced into a confusing situation where the only way to recover funds is to use a backdoor mechanism that bypasses all tournament rules (fees, time-locks, winner conditions).
Likelihood: Medium
This scenario occurs whenever the deposit function is called with a receiver address different from msg.sender. This is a standard pattern in many token vaults, making accidental triggering by users or frontends plausible.
Impact: Medium
Broken Core Application Logic: The primary path for participation is broken, preventing users from joining the tournament as intended. This undermines the main purpose of the contract.
Unfairness and User Confusion: It creates a confusing state where neither party can proceed as expected. It forces users to discover and use non-obvious, unintended recovery paths (the standard ERC4626 functions), which also allows them to bypass tournament rules like fees and time-locks.
Failure to Adhere to Protocol Rules: The vulnerability effectively renders the tournament's custom logic optional, as the underlying ERC4626 functions provide a loophole.
The following test demonstrates the broken logic. It shows that when Alice (user1) deposits for Bob (user2), neither can complete the intended participation flow, and their interaction with the tournament logic fails.
Test result
The contract's accounting must be consistent. The address that receives the shares must be the same one that is credited with the stake.
Recommended Fix: Enforce receiver == msg.sender
This is the simplest and safest solution. It disables the problematic feature and ensures the integrity of the protocol's logic.
Alternative Fix: Align All Logic to receiver
If supporting deposits for others is a required feature, then all internal accounting, including share minting, must be consistently keyed to the receiver.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.