-
Notifications
You must be signed in to change notification settings - Fork 6.1k
Consider using fallback {}
instead of function() {}
(S)
#3198
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
Comments
I like that it makes it easier for beginners to look it up when they find such function in the code. This has confused more than one beginner. I prefer not omitting the parentheses because we are still talking about a function. |
What about adding a modifier instead, similar to payable.
|
my 2 cents:
especially because
looks like a weird anonymous constructor function with two modifiers in front of it. |
@decanus Fallback is different to payable/constructor as there can only be a single fallback function. And given its risky use may warrant its on syntactical element. |
The current setup has always made sense to me in the sense of the EVM because it's the "empty" function signature. AKA the default in a switch statement. |
Right, but it's one of those things that only make sense after you learn about it, and it's not easy to find the right answers. |
Good point. |
Actually I think we should even split the semantics of the fallback function into two: One function that is called only if there is value and zero data (the "receive ether trigger function") and one function that is called as a "wildcard", if no other function matches (this should be considered a low-level feature). |
I like the idea of splitting it up.
…On Mon, Dec 4, 2017 at 12:08 PM chriseth ***@***.***> wrote:
Actually I think we should even split the semantics of the fallback
function into two:
One function that is called only if there is value and zero data (the
"receive ether trigger function") and one function that is called as a
"wildcard", if no other function matches (this should be considered a
low-level feature).
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#3198 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAAJ0LkyhhXChwpUE5xo6y9p5Iecyc2lks5s89KhgaJpZM4QcinE>
.
|
I have been thinking about that too. Utility contracts, for example, may have a single fallback function that decodes parameters and stores or forwards them somewhere else. |
I like this idea. It adds the needed "default" variable to the current switch case concept wrt to how functions in a contract currently execute. |
@axic what do you think about having a wildcard function and a "receive ether" function? |
@chriseth what is a "wildcard function" in this instance? |
A wildcard function is one that is executed if a function selector is given, but it does not match any defined functions. The "receive ether" function is run if no calldata is given. |
Ahhhh...so it's basically a default logic statement as opposed to a default receive statement. You're splitting the fallback into two portions...which tbf is a good design decision imo for safety, but how to do this gracefully in the language is a different matter. What would the syntax look like? |
(I actually thought I've answered this issue.)
Sounds good, but not sure about the naming and if the only point of the non-wildcard function is to receive ether, then it would have I see a couple of different options:
Though I think we cannot really use the words Option 1):
Option 2):
Option 3):
|
I like the idea of having two separate functions:
|
I would prefer Also,
and it should somehow be made clear that this is a very low-level function that should usually not be implemented. |
Splitting into two functions is a good idea. |
Using the parentheses would make this a breaking change, right? Asking because I remember I had some contracts for testing (not on mainnet) that had a function called |
|
Ooops, completely missed that! 😄 |
Also relevant: #2630. |
It might make sense to not allow the wildcard function together with any other function, but that probably conflicts with upgradable contracts. |
We might also have the wildcard directly drop into inline assembly to show that it is a low-level feature. |
Crazy proposal: we could keep everything to
This would prevent us from flooding the language with more and more keyboards and is still entirely un-ambiguous and explicit... |
That sounds like a reasonably crazy idea. Not sure I like that I like it 😉 |
I like it too. |
And then we can skip |
Not really, since the functions wouldn't be split then |
I wasn't being serious :-). A potential problem in skipping |
The problem is that to be entirely un-ambiguous we need to require the |
I would prefer to make it more visible that a contract is doing something weird. A contract should not just react on all signatures. If it does, it should be a proxy and have no other functions and people should really know what they are doing. In contrast, a contract that has some functions and can also receive ether is something "regular" and the function that is called when the contract is sent ether should be recognizable from its name (even with limited prior knowledge about the EVM). |
The presence of a |
But yes, I tend to agree that it's probably better to introduce an easily recognizable name for the "receive ether" function - if we can come up with a good one, of course. |
Proposal by @axic: Call the function Only called with zero data and non-zero value. Fallback function ( If there is a payable fallback function but no |
There can only be at most one fallback function. Also of course at most one |
How about |
@loredanacirstea I would really like to avoid the name |
Ah, I'm not set on the name. It can be called something else. I was suggesting to only use 1 function with two optional modifiers: |
Alternative to For the other case I suggested to add arguments to |
I'll start implementing this as |
To clarify, do we now only allow two cases?
|
@axic That's what viper does, but I think we don't want to force ether==0 for the "fallback" case, but instead allow "fallback" to be "payable", i.e the basic distinction is
And case 1 is further divided as: I'm currently still changing the parser, but there's still some details to iron out - e.g. what happens for "calldata length = 0" and "ether = 0"? |
Also still open: should |
I think empty data should always execute the receive function. |
I'm voting for optionally returning bytes memory. |
@chriseth now suggested to change the semantics slightly - if there is no receive-ether-function, then |
Done in #7385 |
Not sure which is better:
The text was updated successfully, but these errors were encountered: