• YouTube Channel
  • System Status
  • VS Code Extension
  • Shadowing Reserved Keyword

    Overview

    What is the Shadowing Reserved Keyword vulnerability?

    The Solidity language specifies a number of reserved keywords that may be added as functionality to the language in the future. If contracts use these keywords today, they risk compilation failure or logical inconsistency with potential updates to the language in the future. While newer versions of the Solidity compiler restrict usage of these keywords, older versions do not, so if using a vulnerable version, the keywords should be carefully avoided.

    Further reading: Solidity Documentation: Reserved Keywords

    Technical example of vulnerable code

      // SPDX-License-Identifier: Unlicense
      pragma solidity ^0.4.0;
    
      contract OwnableMutable {
          event ChangedVar(string changedVarName);
    
          address public owner;
          // Other management state variables would go here
    
          modifier mutable(string varName) {
              _;
              emit ChangedVar(varName);
          }
    
          constructor() public {
              owner = msg.sender;
          }
    
          function updateOwner(address _newOwner) public mutable("owner") {
              require(msg.sender == owner, "Only the current owner can assign a new owner");
              owner = _newOwner;
          }
    
          // Additional functionality omitted for brevity
      }
    
    

    In the example above, contract OwnableMutable represents an ownership pattern contract with additional functionality to log when key state variables are changed by functions. The modifier that it uses for this purpose, mutable(), uses a name that is now a reserved keyword in the Solidity language. As such, new contracts will be unable to integrate successfully with this pattern as written.

    Technical example of how to fix the vulnerability

      // SPDX-License-Identifier: Unlicense
      pragma solidity ^0.4.0;
    
      contract OwnableMutableUpdated {
          event ChangedVar(string changedVarName);
    
          address public owner;
          // Other management state variables would go here
    
          modifier mutatesVar(string varName) {
              _;
              emit ChangedVar(varName);
          }
    
          constructor() public {
              owner = msg.sender;
          }
    
          function updateOwner(address _newOwner) public mutatesVar("owner") {
              require(msg.sender == owner, "Only the current owner can assign a new owner");
              owner = _newOwner;
          }
    
          // Additional functionality omitted for brevity
      }
    
    

    In the revised example above, contract OwnableMutableUpdated has renamed the modifier for tracking changed state variables to not collide with the mutable reserved keyword.