• YouTube Channel
  • System Status
  • VS Code Extension
  • Uninitialized Local Storage

    Overview

    What is the Uninitialized Local Storage vulnerability?

    In the context of Solidity, reference variables may have different classifications of data location, indicating that the referenced data is an in-memory instance or a reference to stored data that is part of the state of the Ethereum Virtual Machine (EVM). For variables that reference storage locations, uninitialized variables will by default point to the first storage slot of the referenced smart contract, which may contain other data. In earlier versions of Solidity, the compiler would allow contracts making such references to compile, which could lead to inadvertent corruption of the contract state.

    Further reading: Solidity Documentation: Data location

    Technical example of vulnerable code

      // SPDX-License-Identifier: Unlicense
      pragma solidity 0.4.10;
    
      contract UserProfileManager {
          struct UserProfile {
              string name;
              uint256 balance;
          }
    
          mapping(address => UserProfile) public userProfiles;
    
          // Function to initialize a user profile
          function createUserProfile(address user, string name, uint256 initialBalance) external {
              userProfiles[user] = UserProfile(name, initialBalance);
          }
    
          // Function intended to update only the user's balance,
          // but incorrectly manipulates a local storage variable leading to unintended behavior
          function updateUserBalance(address user, uint256 newBalance) external {
              // Uninitialized local storage variable intended to point to a user's profile
              UserProfile storage userProfile; // This line is missing initialization!
    
              // The developer intended to update only the balance, not realizing `userProfile` points to slot 0
              userProfile.balance = newBalance; // This inadvertently overwrites the first slot of the contract storage
          }
    
          // Additional smart contract functionality omitted for brevity
      }
    
    

    In the example above, contract UserProfileManager utilizes a custom struct, UserProfile, to manage certain state data. In function updateUserBalance(), a reference to a user profile in storage is created, but is not initialized. Modifying the storage data pointed to by this reference can subsequently corrupt the state of the contract.

    Technical example of how to fix the vulnerability

      // SPDX-License-Identifier: Unlicense
      pragma solidity 0.4.10;
    
      contract UserProfileManagerUpdated {
          struct UserProfile {
              string name;
              uint256 balance;
          }
    
          mapping(address => UserProfile) public userProfiles;
    
          // Function to initialize a user profile
          function createUserProfile(address user, string name, uint256 initialBalance) external {
              userProfiles[user] = UserProfile(name, initialBalance);
          }
    
          function updateUserBalance(address user, uint256 newBalance) external {
              UserProfile storage userProfile = userProfiles[user];
    
              userProfile.balance = newBalance;
          }
    
          // Additional smart contract functionality omitted for brevity
      }
    
    

    In the revised example above, contract UserProfileManagerUpdated now properly assigns the reference in function updateUserBalance to a specific instance of a UserProfile struct, avoiding the problem associated with the default pointer location.