solidity icon indicating copy to clipboard operation
solidity copied to clipboard

Allow public state variable with private setter

Open fulldecent opened this issue 3 years ago • 5 comments

Usage

Sometimes it is required to a make a contract which is intended to be inherited. And the designer wants to ensure that the inherited will not change a specific storage variable. But at the same time this storage variable may be readable.

public(get) internal(get) private(get)
public(set) :x: There are no public setters. :x: There are no public setters. :x: There are no public setters.
internal(set) This is currently known as public. This is current known as internal. Currently you can only implement this with private storage variable and an internal setter function.
private(set) Currently you can only implement this with private storage variable and a public getter function. Currently you can only implement this with private storage variable and an internal getter function. This is currently known as private.

Existing code snippet

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

abstract contract ThreeChiefOfficers {
    /// @dev The account that can only reassign officer accounts
    address private _executiveOfficer;

    /// @notice Get the chief executive officer
    /// @return The chief executive officer account
    function executiveOfficer() public returns (address) {
        return _executiveOfficer;
    }
    // ...
}

Proposed equivalent snippet

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

abstract contract ThreeChiefOfficers {
    /// @notice Get the chief executive officer
    /// @dev The account that can only reassign officer accounts
    address public(get) private(set) executiveOfficer;
    // ...
}

fulldecent avatar Mar 20 '22 20:03 fulldecent

From a practical point of view, setters almost always have some access controls on them. Because of that, I don't see a need for compiler generated setters.

hrkrshnn avatar Mar 21 '22 18:03 hrkrshnn

This issue is not about compiler generated setters.

This issue is about disallowing a subclass from accessing the setter of the parent.

fulldecent avatar Mar 21 '22 18:03 fulldecent

@fulldecent The syntax is not quite clear to me:

abstract contract ThreeChiefOfficers {
    /// @notice Get the chief executive officer
    /// @dev The account that can only reassign officer accounts
    address public(get) private(set) executiveOfficer;
    // ...
}

Would private(set) create a compiler generated setter? If not, how does the compiler connect the declaration to the actual setter?

hrkrshnn avatar Mar 22 '22 12:03 hrkrshnn

There is no generated setter function.

The expression is meant to indicate that an inheriting contract will NOT be allowed to use that state variable as an l-value.

fulldecent avatar Mar 22 '22 12:03 fulldecent

Here are some actual use cases where this feature would be used today:

  • ERC-721 implementation where the base class wants to allow overriding the baseURL variable (OZ does this)
  • A owner implementation (ERC-5313 (DRAFT)) where changing the owner does something (like changing royalties) and therefore a subclass cannot edit the _owner variable directly.
  • Libraries ("data structures") like queue and list, where there is some validation of the input variables (so directly setting the storage variables might lead to an unexpected state)

fulldecent avatar Aug 05 '22 19:08 fulldecent

This issue has been marked as stale due to inactivity for the last 90 days. It will be automatically closed in 7 days.

github-actions[bot] avatar Mar 24 '23 12:03 github-actions[bot]

Hi everyone! This issue has been automatically closed due to inactivity. If you think this issue is still relevant in the latest Solidity version and you have something to contribute, feel free to reopen. However, unless the issue is a concrete proposal that can be implemented, we recommend starting a language discussion on the forum instead.

github-actions[bot] avatar Apr 01 '23 12:04 github-actions[bot]