Vanguard

First Flight #56
Beginner FriendlyDeFiFoundry
0 EXP
Submission Details
Impact: high
Likelihood: high

[H01] `_resetPerAddressTracking()` Does Not Reset User Data

Author Revealed upon completion

Root + Impact

Description

The phase transition reset function is completely broken, only resetting tracking for address(0) instead of all users.

Note: This issue is interconnected with H-02 (Router vs User Address). Both must be fixed together - see Combined Fix section below.

Vulnerability Details

Location: src/TokenLaunchHook.sol:189-192

function _resetPerAddressTracking() internal {
addressSwappedAmount[address(0)] = 0;
addressLastSwapBlock[address(0)] = 0;
}

The function name suggests it should reset per-address tracking on phase transitions, but it only clears data for address(0), which is never a valid swapper address.

Risk

Likelihood:

  • Every phase transition (Phase 1 to Phase 2, Phase 2 to Phase 3) triggers _resetPerAddressTracking()

  • All users who swapped in previous phases will have their limits carried over

  • This happens automatically at block boundaries defined by phase1Duration and phase2Duration

Impact:

  • Per-address swap limits accumulate across phases instead of resetting

  • Users who swapped 0.5% in Phase 1 can only swap 2.5% in Phase 2 (instead of full 3%)

  • The entire phase-based limit system is fundamentally broken

  • Anti-bot protection is severely compromised

Proof of Concept

function test_trackingNotReset() public {
// User swaps in Phase 1
vm.deal(user1, 10 ether);
vm.prank(user1);
swapRouter.swap{value: 0.005 ether}(...);
uint256 swappedPhase1 = antiBotHook.addressSwappedAmount(address(swapRouter));
// Transition to Phase 2
vm.roll(block.number + phase1Duration + 1);
vm.prank(user1);
swapRouter.swap{value: 0.001 ether}(...);
// Swap amount was NOT reset - it accumulated
uint256 swappedPhase2 = antiBotHook.addressSwappedAmount(address(swapRouter));
assertGt(swappedPhase2, swappedPhase1); // Proves tracking wasn't reset
}

Recommendations

Important: Any fix for H-01 that uses sender will NOT work because sender is the router address (see H-02). Both issues must be fixed together.

Implement proper tracking reset. Options:

  1. Use a phase-indexed mapping: mapping(uint256 => mapping(address => uint256))

  2. Store a phase number with each user's data and reset on mismatch

  3. Use a nonce that increments on phase change

mapping(address => uint256) public addressPhase;
function _beforeSwap(...) internal override returns (...) {
// Reset if user's tracked phase differs from current
if (addressPhase[sender] != currentPhase) {
_resetPerAddressTracking(sender)
addressPhase[sender] = currentPhase;
}
// ... rest of logic
}
function _resetPerAddressTracking(address sender) internal {
addressSwappedAmount[sender] = 0;
addressLastSwapBlock[sender] = 0;
}

Support

FAQs

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

Give us feedback!