BriVault

First Flight #52
Beginner FriendlySolidity
100 EXP
View results
Submission Details
Impact: low
Likelihood: low
Invalid

Inconsistent Timing Boundary Checks Allow Deposit After Event Start

Root + Impact

Description

  • Both deposit and join operations should be prevented once the event starts to ensure fair participation and prevent late entries that could exploit known tournament information.

  • The inconsistent boundary checks create a narrow window at exactly block.timestamp == eventStartDate where deposit() is blocked but joinEvent() is still allowed. This inconsistency means users who deposited earlier can still join at the exact start time, while new deposits are prohibited. While the practical impact is minimal (affecting only transactions mined in the exact block where block.timestamp == eventStartDate), it creates logical inconsistency in the protocol's timing enforcement and could lead to edge-case scenarios where a user successfully deposits in one block but cannot join in the same block due to timestamp progression.

function deposit(uint256 assets, address receiver) public override returns (uint256) {
require(receiver != address(0));
@> if (block.timestamp >= eventStartDate) {
revert eventStarted();
}
// ... rest of function
}
function joinEvent(uint256 countryId) public {
if (stakedAsset[msg.sender] == 0) {
revert noDeposit();
}
if (countryId >= teams.length) {
revert invalidCountry();
}
@> if (block.timestamp > eventStartDate) {
revert eventStarted();
}
// ... rest of function
}

Risk

Likelihood:

  • Occurs only when transactions are mined in blocks with block.timestamp exactly equal to eventStartDate, which represents a very narrow time window (typically one 12-second block on Ethereum).

  • The inconsistency requires users to have previously deposited and attempt to join at the precise moment the event starts, which is an uncommon timing scenario that most users would not intentionally target or encounter.

Impact:

  • The inconsistency creates minor operational confusion where users who deposited just before event start can still join at exactly eventStartDate, while new users attempting to participate at that exact timestamp are blocked from depositing.

  • This affects code maintainability and could lead to unexpected behavior in edge cases, though it does not directly result in fund loss or protocol failure under normal operating conditions.

Proof of Concept

N/A

Recommended Mitigation

standardises the boundary checks for consistent behaviour.

function deposit(uint256 assets, address receiver) public override returns (uint256) {
require(receiver != address(0));
- if (block.timestamp >= eventStartDate) {
+ 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;
}
Updates

Appeal created

bube Lead Judge 19 days ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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

Give us feedback!