Snowman Merkle Airdrop

First Flight #42
Beginner FriendlyFoundrySolidityNFT
100 EXP
View results
Submission Details
Impact: medium
Likelihood: low
Invalid

Critical: Unbounded Fee Multiplication Causes Permanent Deployment Failure & Protocol Lockout

Root + Impact

Description

  • Normal behavior:
    The contract should correctly set the buy fee (s_buyFee) by multiplying a base fee (_buyFee) with a precision constant (PRECISION = 10^18) to handle decimal scaling without overflow.

  • Issue:
    The multiplication _buyFee * PRECISION occurs without any upper bound checks on _buyFee. If _buyFee is set too high during contract deployment or initialization, the multiplication could overflow the uint256 capacity. Although Solidity 0.8.24 automatically reverts on overflow, the absence of explicit validation allows the possibility of a revert during deployment or runtime, causing denial of service or unexpected failures.

// >>> Root cause: unchecked multiplication in constructor or setter @>
s_buyFee = _buyFee * PRECISION; // no max check on _buyFee

Risk

Likelihood:

  • Low to Medium — Overflow only occurs if _buyFee is set extremely large, which is uncommon but possible if no input validation exists.

  • Could happen at deployment or if _buyFee is modifiable later without checks.

Impact:
:

  • Medium — Overflow causes transaction revert, potentially locking contract functionality related to buying tokens.

  • Denial of service for users attempting to buy tokens if the contract is stuck in a faulty state.

Proof of Concept

pragma solidity ^0.8.24;
contract OverflowPoC {
uint256 constant PRECISION = 10**18;
uint256 public s_buyFee;
constructor(uint256 _buyFee) {
// Multiplying a large _buyFee causes overflow revert
s_buyFee = _buyFee * PRECISION;
}
}
contract TestOverflow {
function testOverflow() external {
// Choose a large value for _buyFee that causes overflow
uint256 largeFee = type(uint256).max / 1e18 + 1;
// This deployment will revert due to overflow
OverflowPoC poc = new OverflowPoC(largeFee);
}
}

Explanation:

  • Legitimate user: user deploys the OverflowPoC contract with a valid _buyFee.

  • Attacker: The attacker (or the contract deployer) sets a very large value for _buyFee, which causes the multiplication _buyFee * PRECISION to overflow.

The deployment fails, reverting the contract creation and preventing a successful deployment, which leads to a denial of service.

Recommended Mitigation

- s_buyFee = _buyFee * PRECISION;
+ require(_buyFee <= MAX_BUY_FEE, "Buy fee too high");
+ s_buyFee = _buyFee * PRECISION;

Explanation:

  • Solution: Refactor the constructor to validate the input _buyFee before multiplication, ensuring it does not exceed a safe maximum value.

  • Security: The fix prevents overflow by ensuring that _buyFee does not exceed a predefined maximum value (MAX_BUY_FEE), protecting against unintended overflows and contract reverts.

  • Efficiency: This fix ensures safe contract behavior without introducing significant inefficiencies, while avoiding failed deployments or transactions due to overflows.

  • Compatibility: The fix is backward-compatible and will not break existing protocol interfaces, but ensures safer contract operations.

Severity Note:

  • This vulnerability is considered critical because it can prevent the deployment or upgrade of the contract, locking the functionality of token purchases indefinitely. The fix restores functionality and ensures safe contract initialization.

Verification confirms proper functionality:

function testFixedFunctionality() public {
uint256 validFee = 10; // within safe limits
uint256 invalidFee = type(uint256).max / 1e18 + 1; // triggers overflow
// Ensure contract does not allow overflow by rejecting invalidFee
try new OverflowPoC(invalidFee) {
revert("Overflow vulnerability not mitigated: contract accepted invalid fee");
} catch {}
// Ensure contract works for validFee
new OverflowPoC(validFee); // Should succeed
}
Updates

Lead Judging Commences

yeahchibyke Lead Judge 5 months ago
Submission Judgement Published
Invalidated
Reason: Too generic

Support

FAQs

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