Santa's List

AI First Flight #3
Beginner FriendlyFoundry
EXP
View results
Submission Details
Severity: low
Valid

`collectPresent` can be called indefinitely due to missing upper time bound

Description

The contract is intended to allow users to collect presents around Christmas, within a limited time window. The documentation mentions that the Christmas date is approximate and that collecting slightly before or after Christmas is acceptable.

However, the current implementation only enforces a lower-bound timestamp check and does not place any upper bound on when collectPresent can be called. Once the Christmas timestamp has passed, the function remains callable forever.

This allows users to collect presents long after the intended Christmas period has ended, which breaks the expected time-based restrictions and allows late minting without limits.

function collectPresent() external {
if (block.timestamp < CHRISTMAS_2023_BLOCK_TIME) {
revert SantasList__NotChristmasYet();
}
@> // No upper-bound check exists
...
}

Risk

Likelihood: High

  • Once the Christmas timestamp has passed, the function can be called at any future time.

  • This does not require special conditions and will always be possible after the initial date.

Impact: High

  • Users can mint presents long after the intended Christmas period.

  • This can lead to unlimited late minting and breaks assumptions around scarcity and fairness.

  • The protocol’s time-based logic no longer enforces a meaningful collection window.


Proof of Concept

This test shows that collectPresent can still be called successfully long after Christmas has passed.

function test_CanCollectLongAfterChristmas() public {
// Warp time far beyond Christmas
vm.warp(CHRISTMAS_2023_BLOCK_TIME + 30 days);
// collectPresent still succeeds due to missing upper-bound check
santasList.collectPresent();
}

The call succeeds even though the collection window should reasonably be closed.


Recommended Mitigation

Add an upper-bound timestamp check to ensure collectPresent can only be called within the intended Christmas time window.

//Errors
+ revert SantasList__ChristmasEnded();
function collectPresent() external {
if (block.timestamp < CHRISTMAS_2023_BLOCK_TIME) {
revert SantasList__NotChristmasYet();
}
+ if (block.timestamp > CHRISTMAS_2023_BLOCK_TIME + 1 days) {
+ revert SantasList__ChristmasEnded();
+ }
if (balanceOf(msg.sender) > 0) {
revert SantasList__AlreadyCollected();
}
if (s_theListCheckedOnce[msg.sender] == Status.NICE && s_theListCheckedTwice[msg.sender] == Status.NICE) {
_mintAndIncrement();
return;
} else if (
s_theListCheckedOnce[msg.sender] == Status.EXTRA_NICE
&& s_theListCheckedTwice[msg.sender] == Status.EXTRA_NICE
) {
_mintAndIncrement();
i_santaToken.mint(msg.sender);
return;
}
revert SantasList__NotNice();
}
Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge about 4 hours ago
Submission Judgement Published
Validated
Assigned finding tags:

[L-01] collectPresent() can be called at anytime after christmas

## Description The christmas present should only be collected with 24 hours before or after christmas. But the present can be minted at anytime after christmas. ## Vulnerability Details Documenation mentioned that "The Christmas date is approximate, if it's more then 24 hours before or after Christmas, please report that. Otherwise, it's OK." The `collectPresent()` has only checked that the present cannot be collected before the christmas. But hasn't checked in the case of after christmas collection. ```javascript function collectPresent() external { if (block.timestamp < CHRISTMAS_2023_BLOCK_TIME) { revert SantasList__NotChristmasYet(); } if (balanceOf(msg.sender) > 0) { revert SantasList__AlreadyCollected(); } if (s_theListCheckedOnce[msg.sender] == Status.NICE && s_theListCheckedTwice[msg.sender] == Status.NICE) { _mintAndIncrement(); return; } else if ( s_theListCheckedOnce[msg.sender] == Status.EXTRA_NICE && s_theListCheckedTwice[msg.sender] == Status.EXTRA_NICE ) { _mintAndIncrement(); i_santaToken.mint(msg.sender); return; } revert SantasList__NotNice(); } ``` `uint256 public constant CHRISTMAS_2023_BLOCK_TIME = 1_703_480_381;` The UTC time for this epoch is : `Monday, 25 December 2023 04:59:41` . The present can only be collected after approx 5 hours after the christmas arrived. But it can be collectable at anytime after Christmas. As there is no check for the after christmas case. ## Impact The impact of this vulnerability is that the intended use of the protocol is not acquired. Proof Of Code : ```javascript function testCollectPresentNiceAfterChristmas() public { vm.startPrank(santa); santasList.checkList(user, SantasList.Status.NICE); santasList.checkTwice(user, SantasList.Status.NICE); vm.stopPrank(); vm.warp(1703900189); // Saturday, 30 December 2023 01:36:29 vm.startPrank(user); santasList.collectPresent(); assertEq(santasList.balanceOf(user), 1); vm.stopPrank(); } ``` Add this test to `SantasListTest.t.sol` and run `forge test --mt testCollectPresentNiceAfterChristmas` to test. You can observe that the present is collectable at Saturday, 30 December 2023 01:36:29. ## Recommendations Include check for the after 24 hours of christmas. ```diff function collectPresent() external { - if (block.timestamp < CHRISTMAS_2023_BLOCK_TIME) { + if (block.timestamp < CHRISTMAS_2023_BLOCK_TIME && block.timestamp > 1703554589 ) { revert SantasList__NotChristmasYet(); } if (balanceOf(msg.sender) > 0) { revert SantasList__AlreadyCollected(); } if (s_theListCheckedOnce[msg.sender] == Status.NICE && s_theListCheckedTwice[msg.sender] == Status.NICE) { _mintAndIncrement(); return; } else if ( s_theListCheckedOnce[msg.sender] == Status.EXTRA_NICE && s_theListCheckedTwice[msg.sender] == Status.EXTRA_NICE ) { _mintAndIncrement(); i_santaToken.mint(msg.sender); return; } revert SantasList__NotNice(); } ```

Support

FAQs

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

Give us feedback!