-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
Summary
Add a detector that identifies public state variables containing complex structs where automatic getters omit certain members, potentially causing confusion and incorrect assumptions about data accessibility.
Motivation
Solidity automatically generates getter functions for public state variables. However, these getters have limitations when dealing with complex data structures:
- Arrays and mappings within structs are omitted from the generated getter
- Nested structs with arrays/mappings are partially omitted
- Developers may assume all struct members are accessible via the getter
This behavior is not immediately obvious and can lead to:
- Incorrect assumptions about data availability
- Inefficient workarounds when data appears inaccessible
- Security issues if access control depends on getter visibility
- Integration problems with external contracts or front-ends
Problem Description
When a struct contains arrays or mappings, Solidity's automatic getter will skip these members:
struct UserData {
string name; // ✓ Included in getter
uint256 balance; // ✓ Included in getter
uint256[] tokenIds; // ✗ Omitted from getter
mapping(address => uint256) allowances; // ✗ Omitted from getter
}
contract Example {
UserData public userData; // Getter won't return tokenIds or allowances
}Example Vulnerable Patterns
contract ProblematicPatterns {
// Pattern 1: Direct struct with arrays/mappings
struct Config {
address owner;
uint256[] limits; // Won't be in getter
mapping(address => bool) whitelist; // Won't be in getter
}
Config public config; // Getter omits limits and whitelist
// Pattern 2: Nested structs
struct Inner {
uint256[] values; // Won't be accessible
}
struct Outer {
Inner data; // Partially accessible
string name;
}
Outer public settings; // Getter omits Inner.values
// Pattern 3: Array of structs with complex members
struct Token {
string symbol;
address[] holders; // Omitted when accessing array elements
}
Token[] public tokens; // Individual token getters omit holders
}Recommended Solutions
The detector should suggest alternatives:
contract ImprovedPatterns {
struct Config {
address owner;
uint256[] limits;
mapping(address => bool) whitelist;
}
// Solution 1: Make variable private/internal and create custom getter
Config private config;
function getConfig() external view returns (
address owner,
uint256[] memory limits
) {
return (config.owner, config.limits);
}
// Solution 2: Separate simple and complex data
struct SimpleConfig {
address owner;
uint256 limitCount;
}
SimpleConfig public simpleConfig;
uint256[] public limits;
}Expected Output
Complex struct getter detected in ContractName
State variable: config (line 45)
Type: Config
Omitted members:
- limits: uint256[] (line 12)
- whitelist: mapping(address => bool) (line 13)
Impact: Automatic getter does not return these members
Recommendation: Create a custom getter function or separate complex members
Benefits
- Prevent integration issues - External contracts/UIs won't be surprised by missing data
- Improve code clarity - Developers understand data accessibility
- Reduce gas costs - Avoid unnecessary workarounds for accessing "hidden" data
- Educational value - Teaches Solidity's getter limitations
- Better API design - Encourages thoughtful public interface design
Priority
Medium-High - While not directly a security vulnerability, this issue frequently causes integration problems, increases development time, and can indirectly lead to security issues when developers implement workarounds. It's particularly important for contracts intended to be integrated with other systems.