# Global `s_earnTimer` allow users to block each other from farmning Snow tokens
## Description
* The `Snow` contract allows users to "earn" 1 Snow token every 1 week by calling `earnSnow()`. This feature is supposed to be individual to each user, enforcing a 1-week cooldown between claims.
* However, the `s_earnTimer` variable is implemented as a **single global timestamp**, not per-user. This means **all users share the same timer**, and one user's interaction affects everyone else. As a result, users can either block others from earning or front-run each other, depending on who calls the function first after the timer resets.
```javascript
// earnSnow function
function earnSnow() external canFarmSnow {
if (s_earnTimer != 0 && block.timestamp < (s_earnTimer + 1 weeks)) {
revert S__Timer();
}
_mint(msg.sender, 1);
s_earnTimer = block.timestamp;
}
```
## Risk
**Likelihood**:
* Any time multiple users attempt to claim rewards using `earnSnow()`, they are subject to race conditions. This will **always** occur in production usage.
* A malicious user can grief others by calling `earnSnow()` repeatedly every week, effectively preventing others from earning tokens.
**Impact**:
* Users are unfairly blocked from accessing the rewards they are entitled to.
* Leads to centralization of token distribution and a poor user experience, possibly breaking economic assumptions of fairness.
## Proof of Concept
The following proves how one user can set the global timer and disallowing others from farming Snow Tokens.
```javascript
// Assume Alice calls earnSnow(), sets the global timer
vm.prank(alice);
snow.earnSnow(); // works
// Immediately after, Bob tries to call earnSnow()
vm.prank(bob);
snow.earnSnow(); // fails due to s_earnTimer not being expired
```
## Recommended Mitigation
- Use a mapping instead of a global variable
```diff
- uint256 private s_earnTimer;
+ mapping(address => uint256) private s_earnTimer;
```
```diff
- if (s_earnTimer != 0 && block.timestamp < (s_earnTimer + 1 weeks)) {
+ if (s_earnTimer[msg.sender] != 0 && block.timestamp < (s_earnTimer[msg.sender] + 1 weeks)) {
revert S__Timer();
}
- s_earnTimer = block.timestamp;
+ s_earnTimer[msg.sender] = block.timestamp;
```