Simple code:
pragma solidity 0.8.4;
contract A {
uint256 public constant X = 1;
}
contract B is A {
uint256 override public constant X = 2;
}
Unfortunately that errors on compile:
TypeError: Cannot override public state variable.
--> contracts/mocks/StakePoolMock.sol:4:5:
|
4 | uint256 public constant X = 1;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Note: Overriding public state variable is here:
--> contracts/mocks/StakePoolMock.sol:8:5:
|
8 | uint256 override public constant X = 2;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Is there any way to override public constants?
Short answer: No. You can only override functions in Solidity.
Long answer:
Interestingly, since the compiler generates getter functions for public state variables (including constants), you can actually use them to override functions (Contracts > Inheritance > Function Overriding):
Public state variables can override external functions if the parameter and return types of the function matches the getter function of the variable
While public state variables can override external functions, they themselves cannot be overridden.
So if X
were a function, this would be completely fine:
contract A {
function X() external virtual returns (uint256) {
return 1;
}
}
contract B is A {
uint256 public constant override X = 2;
}
You cannot do it the other way around though and the reason is that this might require removing the slot already reserved for the state variable. The base contract might contain code that accesses that slot through the variable so it would not be safe for the compiler to allow that.
However this reasoning does not apply to constants - they do not occupy any storage. It's also not a problem when overriding a variable with a variable or a constant with a constant. This seems to be a purely syntactical limitation so if you have a strong use case, you might try submitting a feature request. The thing is - is it really a constant if you want to change its value, even if it's only once? I think that in most languages this would not work. You might be able to shadow the constant with a new one but not really override in the full sense of the word - i.e. in such a way that functions called from the base class would see the changed value.
Your use case might be better served with an immutable
, which is a kind of "runtime constant". Unlike a compile-time constant, it's not subject to all the same optimizations the compiler can perform on constants and cannot be used in contexts where a true constant is required (e.g. you cannot use it to define the length of a static array) but it cannot be changed at runtime and does not occupy any storage so it might still fit your requirements. It can be assigned to only once, at construction time and the result is then hard-coded in the bytecode produced by the constructor.
contract A {
uint256 public immutable X;
constructor(uint256 _x) {
X = _x;
}
}
contract B is A(2) {}
The value of the constant variable is assigned during the compiling process then stored in the memory. Unfortunately you can't alter it.
I don't know the purpose of X
in your code, but simple state variables can be reassigned easily and by using the onlyOwner modifier you will have exclusive access to the function so you can change the variable anytime.
function changeValue(uint256 newValue) public onlyOwner {
X = newValue;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With