BriVault

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

Incorrect timestamp comparisons

Description

The contract uses timestamp comparisons to enforce timing restrictions for various operations. However, two functions use incorrect comparison operators that wrongly allow or prevent operations at boundary timestamps.

The `setWinner()` function checks `if (block.timestamp <= eventEndDate)` which prevents setting the winner at exactly `eventEndDate`, when it should be allowed, because the event has ended. The `joinEvent()` function checks `if (block.timestamp > eventStartDate)` which allows joining at exactly `eventStartDate`, when it should be prevented once the event has started.

function setWinner(uint256 countryIndex) public onlyOwner returns (string memory) {
if (block.timestamp <= eventEndDate) { // @> VULN: Should be < instead of <=
revert eventNotEnded();
}
// ... rest of function ...
}
function joinEvent(uint256 countryId) public {
// ... validation code ...
if (block.timestamp > eventStartDate) { // @> VULN: Should be >= instead of >
revert eventStarted();
}
// ... rest of function ...
}

Risk

**Likelihood**:
* Block timestamps can match exact event boundaries
* Users can time transactions to join when event has already started
* Owner can't set winner at exact event end time
**Impact**:
* Users may join event at the exact start time when they shouldn't be able to
* Owner can't set winner at exact end date, even though the event is over
* Potential race conditions and timing edge cases
* Inconsistent behavior with contract's intended timing logic

Proof of Concept

The PoC test below shows how a user would be able to join at the time when the event starts and the owner would not be able to set the winner at the time when the event has ended.

function test_TimestampEdgeCases() public {
vm.prank(owner);
briVault.setCountry(countries);
vm.startPrank(user1);
mockToken.approve(address(briVault), 5 ether);
briVault.deposit(5 ether, user1);
// Test joinEvent at exact eventStartDate
vm.warp(eventStartDate);
// Should revert but doesn't due to > instead of >=
briVault.joinEvent(10); // This succeeds when it shouldn't
vm.stopPrank();
// Test setWinner at exact eventEndDate
vm.warp(eventEndDate);
vm.prank(owner);
vm.expectRevert(abi.encodeWithSignature("eventNotEnded()"));
briVault.setWinner(10); // This reverts when it shouldn't, because eventEndDate has been reached
}

Recommended Mitigation

Switch the lower or equal to lower on setWinner and the greater to greater or equal on joinEvent.

function setWinner(uint256 countryIndex) public onlyOwner returns (string memory) {
- if (block.timestamp <= eventEndDate) {
+ if (block.timestamp < eventEndDate) {
revert eventNotEnded();
}
// ... rest of function ...
}
function joinEvent(uint256 countryId) public {
// ... validation code ...
- if (block.timestamp > eventStartDate) {
+ if (block.timestamp >= eventStartDate) {
revert eventStarted();
}
// ... rest of function ...
}
Updates

Appeal created

bube Lead Judge 19 days ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
ynyesto Submitter
17 days ago
bube Lead Judge
15 days ago
bube Lead Judge 14 days ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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

Give us feedback!