-
Notifications
You must be signed in to change notification settings - Fork 5.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow immutable
variables to be set in the constructor
#3835
![:rage4: :rage4:](https://github.githubassets.com/images/icons/emoji/rage4.png)
Comments
The |
Two problems that still need to be solved are:
A solution for both might be to provide a fixed slot in memory for the variable which is then stored in code right before the code deploy step, i.e. an immutable variable behaves completely different at construction time than at runtime (which is to be expected). |
I think that the second scenario should revert. Immutable vars should be initializable only once. Also re-reading this made me think if we can extend the EDIT: in the case the public function is called externally and the parameters live in the call data, of course. |
@GNSPS public function arguments have to live in memory, otherwise it is not possible to call it internally. This is different for |
Oh and I don't think it should revert, it should just not compile if you assign an immutable variable twice. |
Oh shoot! Of course! My brain stopped, "not compile" is what I meant, "revert"ing makes no sense in a compile-time mechanism. 😂 |
In my mind, this immutable parameter thing was for the different behavior of public functions when called internally and externally but I can see how this would be so much more confusing and not save that much gas. Could just be juxtaposition of |
![:rage4: :rage4:](https://github.githubassets.com/images/icons/emoji/rage4.png)
This feature would be super nice to have imo. Especially with the istanbul increase of SLOADS, I think this can result in significant optimization gains.
If that turns out to be too complex since the immutable could come from memory or the bytecode, then to not allow for functions which depend on the immutable variable in the constructor seems like a good enough start! |
Discussion: We might want to implement this soonish, maybe with |
I propose there is an error in the test case. Should be: contract Example {
uint public constant I_AM_CONSTANT;
uint public immutable I_AM_IMMUTABLE;
function Example(uint _b) public { // WARNING: This function can be changed to "pure" mutability
I_AM_CONSTANT = _b; // TypeError: Cannot assign to a constant variable.
I_AM_IMMUTABLE = _b;
}
}
Warning added inline |
Nowadays it should rather be |
Re-added "to discuss" because we need to agree about the problems related to reading the variable before its final value has been set. |
Another thing to note: This should only work for value types or at most for types that are statically-sized. In that case, we can reserve a certain spot in the deployed bytecode, do not have to move code around and can keep the metadata cbor struct at the very end. |
Another complication is the order of execution of constructors in the inheritance hierarchy. Because of that, I would also say that accessing a non-initialized immutable should result in a compiler error. |
Here is a blunt way to get this to work in the next version, with further improvement possible later:
If r-value in that constructor is necessary then a workaround exists, the developer can use a temporary variable in the constructor. |
If we want to allow immutable state variables for libraries, then we have to allow them to have a constructor. |
This is fully implemented now. |
This request extends #715, and #3356.
Motivation:
It's very common in Solidity contracts to include storage variables which are never intended to be mutated. An example of this is
decimals
in EIP20. (examples: consensys, Zeppelin)The
decimals
value should never change, but no one declares it asconstant
because they want to be able to set the value in the constructor.This is both less safe, and more expensive because the values need to be written to, and read from storage.
Proposal:
immutable
values should be appended to the runtime bytecode.constant
values are currently placed on the stack usingPUSH_
,immutable
values can be accessed usingCODECOPY
.This approach has additional safety beyond compiler errors, as it's not possible to modify bytecode in the ethereum protocol.
That would look something like this:
Implementation notes:
The text was updated successfully, but these errors were encountered: