-
Notifications
You must be signed in to change notification settings - Fork 5.8k
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
Strengthen the definition of pure
potentially disallowing e.g. codecopy
- or "the future of pure
".
#8153
Comments
pure
potentially disallowing e.g. codecopy
.pure
potentially disallowing e.g. codecopy
- or "the future of pure
".
This is what pure was supposed to be, but it was softened up somehow 😉 |
I agree, pure functions should not be allowed to read from data that can be modified by a constructor. |
I agree, but then |
(sorry for the double-post, missed the comment that discussion about pure should be moved here) @ekpyron Great breakdown (in the linked issue) of the two potential definitions of pure. I have always treated pure as along the lines of "if you call this method on this contract multiple times with the same inputs, you'll get the same result every time no matter what other conditions change between calls". This interpretation generally aligns with what I want as a dapp developer, and it also makes sense that I can kind of see the merits to the other definitions, but IMO "it yields the same result if called multiple times" feels both the most useful and the most natural. Can someone express the argument as to why a user would want pure to mean "provides the same result no matter what bytecode the function is deployed with" is? I want to be careful that we are implementing pure in the most pure (pun intended) way because it offers the best developer experience, not just because it is the strictest definition we can come up with. |
@MicahZoltu the only problem I see is a potential confusion that a pure method in the less restrictive sense yields a different result when moved to a different contract. Or put a different way: In the functional sense, pure means that there is no other state to take into account except the arguments to the function call. On the other hand, when seen at the EVM level, then a pure function always reads the code, because that is what is executed, so maybe it should also be able to use codecopy. Maybe we should ask the same question from the other end: How would you use "pure" as a feature when it is defined in the one or the other way? |
Honestly, I don't use it much. When it does come up in auditing for me, I am usually just using it as a shortcut to avoid going down some particular code path when I need to validate that a call won't read some dirty storage variable. If I would also support splitting
|
Agreement from call: codecopy should not be pure (let alone for consistency with immutable). @ekpyron which other things did you have in mind? |
We should probably go through the list of opcodes to check if there's anything else, but |
This issue just came up again recently, when we realized that we - while we wanted to get all this sorted for 0.7.0 - don't really have consensus about While I think the two ways to think of I think that intuitively there is a difference between However, I'm definitely not saying that we should make the meaning of Still, even if we come to an agreement about this part, we still have to precisely clarify what counts as "state" and what as "input arguments" for those external pure functions, because the distinction is not always entirely clear. |
Your reasoning sounds consistent, @ekpyron . It might be not that confusing to strengthen the restrictions imposed by 'pure` at least for free functions. |
Since the evaluation of a pure function depends on its immutable code, it seems silly to prevent codecopy or reading from immutable variables inside |
The main reason for strengthening
will only work sanely if There is two ways to proceed with this:
Both are OK, but we have an inconsistent mixture right now. 1 would mean that we either need a different way to mark functions "compile-time constant" or merely rely on the compiler to determine whether it is or not (both would be feasible, though). The main question is whether 2 forces things to be |
As someone who is heavy user (and proponent) of pure functions (and functional programming in general), I prefer option 1. It seems reasonable to strive for objective technical accuracy, rather than striving for some subjective semantic accuracy. Immutables end up as in-line litterals. The on-chain byte code for a function that returns a With a perfect decompiler that could translate any on-chain bytecode into human-readable Solidity (as one would write it), the following 4 smart contracts would have identically decompiled
In my opinion, When you deploy a contract to the chain, you already need to wait for the receipt to be sure of its address (i.e. consider a factory that deploys children using the blockhash as a |
Thank you for your input, @deluca-mike ! I think your examples fall a bit short on the most generic case. Of course a function that uses an immutable that in fact is a compile-time constant can be pure in the most strict functional-programming sense. The question is if code whose semantics depend on the time and circumstances it was deployed at can be considered pure or not. |
Just because this has come up in the context of #12860 again: I'm personally starting to change my mind on this issue. In #3835 (comment) I basically argued that it makes a difference whether one considers However, there is a different notion one can use for In this interpretation, it's perfectly fine to read arbitrary calldata and memory in I think the weak notion of it being admissible to call an internal function from an external pure function, is useful - for example in inheritance context (e.g. leaving an internal pure function unimplemented, but calling it, for a derived contract to provide an implementation, which may e.g. read So I'm more and more leaning towards actually weakening There is still merit in decorating internal functions that are compile-time constant, i.e. that only depend on their immediate arguments and are pure in the classical functional sense. However, these days I'd rather introduce a new separate keyword for this property, like C++'s |
follow from #12829 |
This issue has been marked as stale due to inactivity for the last 90 days. |
Hi everyone! This issue has been automatically closed due to inactivity. |
Came up in #3835, in particular #3835 (comment) states the issue.
The main question is: since
view
already allowsstaticcall
, is there any use for the coarse definition ofpure
, that allows for expressions that are not compile-time constant?Personally, I'd say we should officially strengthen pure, so that everything pure can be used in place of compile-time-constant expressions, e.g. the most basic definition of pure is "everything that can be used as array size of a statically sized array".
We could also move towards the opposite direction and e.g. allow reading the address of
this
inpure
functions and weakenpure
to mainly mean "does not read from storage". But then we need yet another stricter concept for compile-time-constant expressions. So I'm not a fan of that course of action :-).The text was updated successfully, but these errors were encountered: