Skip to content
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

VIP: Add keyword for immutable state variables #1164

Closed
buckle2000 opened this issue Dec 30, 2018 · 11 comments · Fixed by #2466
Closed

VIP: Add keyword for immutable state variables #1164

buckle2000 opened this issue Dec 30, 2018 · 11 comments · Fixed by #2466
Labels
Easy Pickings Used to denote issues that should be easy to implement VIP: Approved VIP Approved

Comments

@buckle2000
Copy link

buckle2000 commented Dec 30, 2018

Simple Summary

Add a keyword for state variables of a contract that ensures immutability

Abstract & Motivation

Data marked with this keyword must be set in __init__

This keyword will make code more readable, thus making it more secure.

The keyword might be

  • final
  • immutable
  • frozen
  • ... or whatever

Specification

If the keyword is final, then it can be used like this:

# Auction params
# Beneficiary receives money from the highest bidder
beneficiary: public(final(address))
auctionStart: final(public(timestamp))
auctionEnd: public(final(timestamp))

Immutability is checked only in compile time

Backwards Compatibility

None

Copyright

Copyright and related rights waived via CC0

@buckle2000 buckle2000 changed the title Add keyword to denote immutable data in contract Add keyword for immutable data Dec 30, 2018
@buckle2000 buckle2000 changed the title Add keyword for immutable data Add keyword for immutable state variables Dec 30, 2018
@fubuloubu
Copy link
Member

I like this proposal. It works for the concept of deployment parameters that is a pretty common usecase (for things like the ticker symbol of a token, withdrawal period of Plasma, etc)

As noted, it's basically a hint for auditing and a compile-time check, so not hugely necessary.

Maybe we could allow final constants to not have to be set/accessed with the self.CONSTANT syntax so it fits in the same way as we use constants (only set at deployment instead of in code)

@jacqueswww jacqueswww added the VIP: Discussion Used to denote VIPs and more complex issues that are waiting discussion in a meeting label Jan 2, 2019
@jacqueswww
Copy link
Contributor

jacqueswww commented Jan 2, 2019

Just a note: Marking something as final means it can only be set in __init__ which also means we need to warn that a variables is set to default/zero if not assigned in __init__ (the alternative to the __init__ limitation being a check for 1 assignment maximum).

@fubuloubu
Copy link
Member

fubuloubu commented Jan 2, 2019

Should the compiler throw an Error if it's not set in __init__? I would argue that's unintended behavior and they should either set it or make it a constant.

@jacqueswww
Copy link
Contributor

Yes, this would definitely have to be an error as it violates final.

@fubuloubu fubuloubu changed the title Add keyword for immutable state variables VIP: Add keyword for immutable state variables Jan 7, 2019
@jacqueswww
Copy link
Contributor

Approved 👍

@jacqueswww jacqueswww added the VIP: Approved VIP Approved label Jan 10, 2019
@fubuloubu fubuloubu removed the VIP: Discussion Used to denote VIPs and more complex issues that are waiting discussion in a meeting label Aug 8, 2019
@fubuloubu fubuloubu added the Easy Pickings Used to denote issues that should be easy to implement label Jan 6, 2020
@charles-cooper
Copy link
Member

for gas savings, we can skip SLOADing immutable variables. in the constructor, we can set the values of the immutable variables in a data section of the runtime code and then at runtime use CODECOPY to load the values.

@spinoch
Copy link
Contributor

spinoch commented Feb 22, 2021

I would have expected this functionality to be implemented as part of constant, that feels more intuitive imo

@fubuloubu
Copy link
Member

I would have expected this functionality to be implemented as part of constant, that feels more intuitive imo

A constant gets injected directly into the bytecode during compilation. The suggestion here would be a state variable that can only be set once (during __init__, or potentially during an initialize method w.r.t. create_forwarder_to-style proxies).

It would still be a storage variable. Dynamically assembling the bytecode during deployments is a really difficult exercise, but could be done as an optimization to further reduce code size/gas cost.

@spinoch
Copy link
Contributor

spinoch commented Feb 22, 2021

Right. Thanks for the low-level hints.

It would still be a storage variable. Dynamically assembling the bytecode during deployments is a really difficult exercise, but could be done as an optimization to further reduce code size/gas cost.

I was thinking that one could have some sort of templating similar to say docker-compose or shell scripts where the contracts would get information from an environment variables kind of setup e.g. the code would look like

BENEFICIARY: public(constant(address)) = $BENEFICIARY

and at compile time the value of $BENEFICIARY is read from the environment and replaces the variable name.

This way, it is still a constant at compile time and we have the gas optimizations as well as relatively clean code.
Of course, this would imply having some kind of wrapper at compile time which replaces the placeholder constants for the desired values. One can easily do this using shell tools, but I'm unsure if the cost of maintenance and complexity are worth it

@fubuloubu
Copy link
Member

at compile time the value of $BENEFICIARY is read from the environment and replaces the variable name.

I had a similar idea too, I think it would be useful but IMO that's a new VIP.

In general, I want to support using Vyper as a templating tool too. For example, in yearn-vaults we have a field that's generated based on the git tag, but that requires a lot of management to use correctly. if it instead looked like:

VERSION = public(constant(String[20])) = {{ $VERSION }}
BENEFICIARY: public(constant(address)) = {{ $BENEFICIARY }}

that would be pretty cool

v1.0 Release Candidate automation moved this from To do to Done Nov 13, 2021
@charles-cooper
Copy link
Member

charles-cooper commented Jun 10, 2022

It would still be a storage variable. Dynamically assembling the bytecode during deployments is a really difficult exercise, but could be done as an optimization to further reduce code size/gas cost.

note for those looking at this issue for implementation details: in the current implementation (v0.3.3), immutables are appended to the runtime code during deployment, there is no storage overhead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Easy Pickings Used to denote issues that should be easy to implement VIP: Approved VIP Approved
Projects
Development

Successfully merging a pull request may close this issue.

5 participants