Blockchain 6 min read

How to Prevent Critical Solidity Bugs: Overflow, Underflow, Visibility, Delegatecall & Reentrancy

This article explains common Solidity vulnerabilities—including overflow, underflow, function visibility pitfalls, delegatecall misuse, and reentrancy attacks—illustrates each issue with concrete code examples, and shows how to mitigate them using SafeMath and proper contract design.

Senior Brother's Insights
Senior Brother's Insights
Senior Brother's Insights
How to Prevent Critical Solidity Bugs: Overflow, Underflow, Visibility, Delegatecall & Reentrancy

Overflow & Underflow

Solidity stores integers in 256‑bit slots, so the maximum value is 2**256 - 1. Adding 1 to this maximum wraps around to 0 (overflow), and subtracting 1 from 0 wraps to 2**256 - 1 (underflow). The following contract demonstrates both behaviours:

pragma solidity 0.4.18;

contract OverflowUnderflow {
    uint public zero = 0;
    uint public max = 2**256 - 1;

    function underflow() public {
        zero -= 1; // becomes 2**256 - 1
    }

    function overflow() public {
        max += 1; // becomes 0
    }
}

Although both are dangerous, underflow can be more harmful because it may increase a token balance unintentionally.

Using the SafeMath library prevents these errors by checking for overflow/underflow before performing arithmetic:

pragma solidity 0.4.18;

library SafeMath {
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        if (a == 0) return 0;
        uint256 c = a * b;
        assert(c / a == b);
        return c;
    }
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        assert(b > 0);
        uint256 c = a / b;
        return c;
    }
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        assert(b <= a);
        return a - b;
    }
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        assert(c >= a);
        return c;
    }
}

contract OverflowUnderflow {
    using SafeMath for uint;
    uint public zero = 0;
    uint public max = 2**256 - 1;

    function underflow() public {
        zero = zero.sub(1);
    }

    function overflow() public {
        max = max.add(1);
    }
}

Visibility & Delegatecall

Public functions can be called by any address.

External functions are callable only from outside the contract and use calldata, saving gas.

Private functions are callable only within the defining contract.

Internal functions are callable from the contract and its derived contracts.

Delegatecall executes code from another contract while preserving the caller’s storage, address, and balance. This enables modular libraries but also opens the door to attacks if the called code can modify the caller’s state.

pragma solidity 0.4.18;

contract Delegate {
    address public owner;

    function Delegate(address _owner) public {
        owner = _owner;
    }

    function pwn() public {
        owner = msg.sender; // attacker gains ownership of the calling contract
    }
}

contract Delegation {
    address public owner;
    Delegate delegate;

    function Delegation(address _delegateAddress) public {
        delegate = Delegate(_delegateAddress);
    }

    function attack() public {
        // delegatecall runs Delegate.pwn() in the context of Delegation
        delegate.delegatecall(msg.data);
    }
}

Reentrancy (The DAO Hack)

When a contract uses call with a value, all remaining gas is forwarded to the callee. If the callee re‑enters the vulnerable contract before the caller’s balance is updated, the attacker can drain funds.

function withdraw(uint _amount) public {
    if (balances[msg.sender] >= _amount) {
        // External call forwards all gas
        msg.sender.call.value(_amount)();
        // Balance is reduced only after the call – vulnerable to re‑entrancy
        balances[msg.sender] -= _amount;
    }
}

The DAO attack exploited exactly this pattern, allowing an attacker to repeatedly invoke withdraw before the balance was decremented, draining the contract’s ether.

Mitigations include using the Checks‑Effects‑Interactions pattern, employing transfer (which forwards limited gas), or leveraging re‑entrancy guards.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Blockchainsmart contractsSolidityoverflowReentrancyDelegatecallUnderflow
Senior Brother's Insights
Written by

Senior Brother's Insights

A public account focused on workplace, career growth, team management, and self-improvement. The author is the writer of books including 'SpringBoot Technology Insider' and 'Drools 8 Rule Engine: Core Technology and Practice'.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.