26 Apr, 2023

State Variable Default Visibility (SWC-108)


Visibility in programming influences how easily a variable or function may be accessed from different areas of the code. To specify which sections of the code may access a variable, it can be annotated with a visibility label when it is declared. Languages like JavaScript may do this labelling implicitly or explicitly, as in the case of languages like Solidity.

It is simpler to spot false assumptions about who may use a variable or function when the accessibility of those objects is explicitly labelled. A variable, for instance, can only be accessed by the contract that declared it if it is specified as private. The compiler will produce an error if another contract or an outside user tries to access the variable.

Clarifying the intended purpose and scope of a variable by explicitly labelling its visibility improves both the readability and comprehension of the code. Even though the default behaviour is adequate, it is generally a good programming practise to label the visibility of all variables and functions in order to minimise misunderstanding and potential security flaws.


Solidity, state variables can be declared with one of three visibility modifiers: public, internal, or private.

The public modifier makes a state variable accessible from outside the contract, and also creates an automatically generated getter function to read the value. This means that anyone can read the value of the variable from the blockchain, which can be a security vulnerability if sensitive data is stored in the variable.

The public modifier, on the other hand, makes a state variable only accessible from within the contract. This means that the value cannot be read or modified from outside the contract. However, this does not protect against malicious actors within the contract.

The internal modifier makes a state variable only accessible from within the contract and its derived contracts. This provides a level of protection against malicious actors within the contract and allows derived contracts to access the value.

Contract Samples

Code with a vulnerability

					pragma solidity 0.4.24;

contract TestStorage {

    uint storeduint1 = 15;
    uint constant constuint = 16;
    uint32 investmentsDeadlineTimeStamp = uint32(now); 

    bytes16 string1 = "test1"; 
    bytes32 private string2 = "test1236"; 
    string public string3 = "lets string something"; 

    mapping (address => uint) public uints1; 
    mapping (address => DeviceData) structs1; 

    uint[] uintarray; 
    DeviceData[] deviceDataArray; 

    struct DeviceData {
        string deviceBrand;
        string deviceYear;
        string batteryWearLevel;

    function testStorage() public  {
        address address1 = 0xbccc714d56bc0da0fd33d96d2a87b680dd6d0df6;
        address address2 = 0xaee905fdd3ed851e48d22059575b9f4245a82b04;

        uints1[address1] = 88;
        uints1[address2] = 99;

        DeviceData memory dev1 = DeviceData("deviceBrand", "deviceYear", "wearLevel");

        structs1[address1] = dev1;



Tools for scaning SWC-108

1. Mythril: It is a popular security analysis tool for Ethereum smart contracts. It has a rule to check for missing visibility specifiers.

2. Solhint: It is a linter for Solidity that provides security and style guide validations. It has a rule to check for missing visibility specifiers.

3. Slither: It is a static analysis tool for Solidity that can detect a wide range of security vulnerabilities, including SWC-108.

4. Remix: It is an online IDE for Solidity that provides a static analysis feature to scan for security vulnerabilities, including SWC-108.

The Common Weakness Enumeration (CWE)

CWE-710: Improper Adherence to Coding Standards

Mitigation for SWC-108

1. Explicitly label the visibility of all state variables: As recommended by SWC-108, always specify the visibility of state variables as either public, private, or internal. This will ensure that access to the variables is limited only to the intended parties.

2. Use require statements to check for access control: You can use require statements to check for access control before allowing functions to execute. This can help prevent unauthorized access to state variables.

3. Use access control contracts: You can use access control contracts to manage access to state variables. This involves creating a contract with functions that define the access control rules for state variables, and then inheriting this contract in your main contract.

4. Use libraries: You can also use libraries to manage access control. Libraries are reusable pieces of code that can be deployed and used across multiple contracts. By encapsulating access control logic in a library, you can ensure that it is consistent across multiple contracts.

5. Follow the principle of least privilege: Follow the principle of least privilege when assigning roles and permissions. Only grant the minimum level of access necessary for each role or user.


SWC-108 highlights the importance of explicitly defining the visibility of state variables in Solidity smart contracts. By doing so, developers can avoid making incorrect assumptions about who can access the variable, which can lead to security vulnerabilities. To mitigate this issue, developers should explicitly define the visibility of all state variables in their smart contracts, using the public, internal, or private keywords. Additionally, they can use tools such as Mythril and Slither to scan their contracts for potential issues related to variable visibility. By following these best practices, developers can create more secure smart contracts that are less vulnerable to attacks.

Other Services

Ready to secure?

Let's get in touch