Skip to content

Secure Solidity patterns for gas optimization with unchecked arithmetic. Features production-ready code with circuit breakers, access controls, and event monitoring. Ideal for developers balancing gas efficiency with security in DeFi and Web3 applications. #ethereum #solidity #gas-optimization

Notifications You must be signed in to change notification settings

dariemjnr/safemath

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 

Repository files navigation

safemath

Secure Solidity patterns for gas optimisation with unchecked arithmetic. Features production-ready code with circuit breakers, access controls, and event monitoring. Ideal for developers balancing gas efficiency with security in DeFi and Web3 applications. #ethereum #solidity #gas-optimization

Enhanced SafeMathTester Contract

A secure Solidity smart contract demonstrating safe usage of unchecked arithmetic operations with multiple security patterns.

Table of Contents

Overview

The EnhancedSafeMathTester contract showcases how to securely implement Solidity's unchecked blocks for gas optimization while maintaining robust security guarantees. Since Solidity 0.8.0, arithmetic overflow/underflow checks are performed by default, but using unchecked blocks allows bypassing these checks when appropriate to save gas.

Security Features

This contract implements multiple layers of protection:

  1. Manual Overflow Validation - Pre-checks to mathematically verify operations won't overflow
  2. Bounded Operations - Logic constraints that keep values within safe ranges
  3. Circuit Breaker Pattern - Emergency stop functionality to pause operations if issues are detected
  4. Comprehensive Event Logging - Full audit trail of all value changes
  5. Access Control - Owner-restricted critical functions
  6. Informational Functions - Helpers to monitor proximity to dangerous values

Contract Structure

// State Variables
uint8 public bigNumber = 225;    // Main value we're operating on (uint8 max is 255)
bool public emergencyStop = false;  // Circuit breaker flag
address public owner;               // For access control

// Events
event ValueChanged(uint8 oldValue, uint8 newValue, string operation);
event EmergencyToggled(bool stopped);

// Modifiers
modifier onlyOwner() {...}
modifier whenNotStopped() {...}

// Functions - multiple approaches to safe unchecked arithmetic

Function Documentation

Core Unchecked Operations

unsafeAdd()

Demonstrates basic unchecked increment without safety features. For educational purposes only.

function unsafeAdd() public whenNotStopped {
    uint8 oldValue = bigNumber;
    
    unchecked { 
        bigNumber += 1;
    }
    
    emit ValueChanged(oldValue, bigNumber, "unsafeAdd");
}

safeAdd(uint8 x)

Implements manual overflow validation before performing unchecked addition.

function safeAdd(uint8 x) public whenNotStopped {
    // Manual check before performing unchecked operation
    require(bigNumber <= 255 - x, "Addition would overflow");
    
    uint8 oldValue = bigNumber;
    
    unchecked {
        bigNumber += x;
    }
    
    emit ValueChanged(oldValue, bigNumber, "safeAdd");
}

boundedIncrement()

Uses conditional logic to ensure value stays within safe bounds.

function boundedIncrement() public whenNotStopped {
    uint8 oldValue = bigNumber;
    
    unchecked {
        // Ensure value stays within bounds
        if (bigNumber < 255) {
            bigNumber += 1;
        }
    }
    
    emit ValueChanged(oldValue, bigNumber, "boundedIncrement");
}

doubleIfSafe()

Shows mathematical validation for more complex operations.

function doubleIfSafe() public whenNotStopped {
    // Ensure doubling won't overflow
    require(bigNumber <= 127, "Doubling would overflow");
    
    uint8 oldValue = bigNumber;
    
    unchecked {
        bigNumber *= 2;
    }
    
    emit ValueChanged(oldValue, bigNumber, "doubleIfSafe");
}

Security Controls

toggleEmergencyStop()

Circuit breaker pattern to pause all operations if issues are detected.

function toggleEmergencyStop() public onlyOwner {
    emergencyStop = !emergencyStop;
    emit EmergencyToggled(emergencyStop);
}

setBigNumber(uint8 newValue)

Direct value setting with proper access control.

function setBigNumber(uint8 newValue) public onlyOwner whenNotStopped {
    uint8 oldValue = bigNumber;
    bigNumber = newValue;
    emit ValueChanged(oldValue, bigNumber, "setBigNumber");
}

Informational Functions

getBigNumberStats()

Provides the current value and how close it is to overflowing.

function getBigNumberStats() public view returns (uint8, uint8) {
    return (bigNumber, type(uint8).max - bigNumber);
}

getMaxValue()

Returns the maximum possible value for the data type.

function getMaxValue() public pure returns (uint8) {
    return type(uint8).max; // Returns 255 for uint8
}

Reference Implementation

addWithCheck()

Standard checked arithmetic for comparison - no unchecked block.

function addWithCheck() public whenNotStopped {
    uint8 oldValue = bigNumber;
    
    // This will revert if bigNumber = 255
    bigNumber += 1;
    
    emit ValueChanged(oldValue, bigNumber, "addWithCheck");
}

Use Cases

This contract pattern is valuable for:

  1. Gas-Intensive Applications - When performing many arithmetic operations where gas costs matter
  2. Counter Systems - Where you know values won't reach upper/lower bounds
  3. Educational Purposes - Demonstrating safe vs. unsafe unchecked arithmetic
  4. Mathematical Libraries - When operations are proven safe by design
  5. Rate-Limited Operations - Where bounded increments within validated ranges are needed

Real-World Examples:

  • Token Distribution Systems - When distributing tokens to many accounts
  • Voting Systems - For counting large numbers of votes efficiently
  • Gaming Smart Contracts - For game mechanics with frequent incrementing
  • DeFi Protocols - Where gas optimisation is critical for user affordability

Security Considerations

When using unchecked blocks:

  1. Always Add Validation - Either before the operation or within the block
  2. Document Thoroughly - Explain why the unchecked operation is safe
  3. Consider Value Ranges - Know the maximum possible values your variables can reach
  4. Use For Simple Operations - More complex calculations increase risk
  5. Test Edge Cases - Especially values at or near boundaries

Gas Optimisation

Using unchecked blocks can save approximately:

  • 15-30 gas per addition/subtraction operation
  • 40-60 gas per multiplication operation
  • More for complex operations

This can add up significantly for contracts with many operations or high usage.

Testing Recommendations

When implementing this pattern:

  1. Create unit tests specifically for overflow/underflow scenarios
  2. Test emergency stop functionality
  3. Verify events are emitted correctly
  4. Test access control restrictions
  5. Create fuzz tests with random inputs to verify bounds

Note: This contract uses a uint8 for demonstration purposes. Real-world applications typically use uint256, but the principles remain the same.

About

Secure Solidity patterns for gas optimization with unchecked arithmetic. Features production-ready code with circuit breakers, access controls, and event monitoring. Ideal for developers balancing gas efficiency with security in DeFi and Web3 applications. #ethereum #solidity #gas-optimization

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published