Last updated: December 19, 2024
SCWE-014: Shadowing Variables and Functions
Content in BETA
This content is in beta and still under active development, so it is subject to change any time (e.g. structure, IDs, content, URLs, etc.).
Send Feedback
Relationships
- CWE-1109: Use of Same Variable for Multiple Purposes
CWE-1109
Description: This weakness occurs when a variable is used for multiple purposes in a way that causes confusion, bugs, or unintentional side effects. In the context of smart contracts, shadowing variables leads to such misuse, as it causes ambiguity between different scopes.
Description
Shadowing variables or functions is a scenario where a local variable or function shares the same name as one in a larger or outer scope. This can cause ambiguity and lead to unexpected behavior or bugs, as the inner variable or function hides the outer one. This problem is especially tricky in Solidity due to its inheritance model, where a child contract might unintentionally override parent contract variables or functions.
Key issues:
- Ambiguity: The developer might not be aware that a variable or function is being hidden.
- Unintentional logic errors: It may lead to the wrong variable being accessed, or the wrong function being called.
- Difficulty in debugging: Shadowing makes the code harder to understand and trace, especially in complex contracts or when inheritance is involved.
- Use unique and descriptive names: Always use unique names for variables and functions to avoid shadowing. Use clear, descriptive names for contract variables and functions.
- Avoid redeclaring variables in nested scopes: Ensure that variables or functions in inner scopes don’t conflict with those in outer scopes.
- Static analysis tools: Use static analysis tools to detect and warn about shadowing issues.
Samples
Example of Shadowing Variables and Functions
pragma solidity ^0.4.0;
contract ShadowingExample {
uint public balance;
// This function shadows the 'balance' variable
function deposit(uint balance) public {
// Local variable 'balance' now shadows the contract's balance variable
balance += balance; // This operation affects the local 'balance', not the contract's state variable
}
}
contract Test {
ShadowingExample example;
constructor() public {
example = new ShadowingExample();
}
function testDeposit() public {
example.deposit(100); // Calling the deposit function on the example contract
}
}
In the above example, the parameter balance
in the deposit
function shadows the contract’s state variable balance
. This causes confusion, and the operation balance += balance
; modifies the local variable instead of the contract state variable, leading to unexpected behavior.
Fixed Code
pragma solidity ^0.4.0;
contract ShadowingExample {
uint public balance;
// The parameter is renamed to avoid shadowing the state variable 'balance'
function deposit(uint amount) public {
balance += amount; // Correctly updates the contract's state variable
}
}
contract Test {
ShadowingExample example;
constructor() public {
example = new ShadowingExample();
}
function testDeposit() public {
example.deposit(100); // Calling the deposit function on the example contract
}
}
In the optimized version, the function parameter is renamed from balance
to amount
to avoid shadowing the state variable. This clears up the ambiguity and ensures the function operates on the contract's state variable, not the local variable.