Inaccurate phase calculation inside getCurrentPhase()
Description
During calculation to determine the user phase inside getCurrentPhase() on TokenLaunchHook.sol contract, inaccuracy calculation during phase transition.
function getCurrentPhase() public view returns (uint256) {
if (launchStartBlock == 0) return 0;
uint256 blocksSinceLaunch = block.number - launchStartBlock;
if (blocksSinceLaunch < phase1Duration) {
return 1;
} else if (blocksSinceLaunch < phase1Duration + phase2Duration) {
return 2;
} else {
return 3;
}
}
Risk
Minimal risk as it is only used for getter function
Inaccuracy information from getter function
Likelihood:
Impact:
Proof of Concept
Add bellow function into existing test suite TokenLaunchHook.t.sol
Run test suite with forge test --match-test test_PhaseCalculation -vvv
function test_PhaseCalculation1() public {
assertEq(antiBotHook.getCurrentPhase(), 1, "Should start in phase 1");
vm.roll(block.number + phase1Duration);
console.log("Current phase should be 1, but instead getPhase ", antiBotHook.getCurrentPhase());
assertEq(antiBotHook.getCurrentPhase(), 1, "Should still in phase 1");
}
function test_PhaseCalculation2() public {
assertEq(antiBotHook.getCurrentPhase(), 1, "Should start in phase 1");
vm.roll(block.number + phase1Duration + phase2Duration);
console.log("Current phase should be still 2, but instead getPhase ", antiBotHook.getCurrentPhase());
assertEq(antiBotHook.getCurrentPhase(), 2, "Should be in phase 2");
}
Log output :
Suite result: FAILED. 0 passed; 2 failed; 0 skipped; finished in 13.78ms (424.21µs CPU time)
Ran 1 test suite in 367.03ms (13.78ms CPU time): 0 tests passed, 2 failed, 0 skipped (2 total tests)
Failing tests:
Encountered 2 failing tests in test/TokenLaunchHookUnit.t.sol:TestTokenLaunchHook
[FAIL: Should still in phase 1: 2 != 1] test_PhaseCalculation1() (gas: 20719)
[FAIL: Should be in phase 2: 3 != 2] test_PhaseCalculation2() (gas: 22874)
Recommended Mitigation
Add = sign on the root cause of the code
function getCurrentPhase() public view returns (uint256) {
if (launchStartBlock == 0) return 0;
uint256 blocksSinceLaunch = block.number - launchStartBlock;
- if (blocksSinceLaunch < phase1Duration) {
+ if (blocksSinceLaunch <= phase1Duration) {
return 1;
- } else if (blocksSinceLaunch < phase1Duration + phase2Duration) {
+ } else if (blocksSinceLaunch <= phase1Duration + phase2Duration) {
return 2;
} else {
return 3;
}
}