-
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
Allow nonpayable functions to override payable functions #11253
Comments
This is a duplicate of #3412. But that issue was apparently closed prematurely, so I'm glad to see this back from the dead. |
I remember that we discussed this, but thinking about it for a minute, I cannot see a reason why this should not be allowed. @ekpyron what do you think? |
Apparently, I was for allowing it at some point in #3412 (comment) and @axic half-agreed #3412 (comment), but was still sceptical :-). Without thinking about it too long, I also still don't see a reason why not. |
Tentatively agreed on today's meeting to allow narrowing from payable to non-payable, but keep widening from non-payable to payable disallowed. Narrowing is similar to the case of view vs pure, with the difference that the compiler inserts code (the check for Widening on the other hand would mean that the expected behaviour (fail on value) is not enforced. |
As a non-exhaustive list of auditors, pinging @GNSPS @montyly @Austin-Williams @stbeyer for feedback. |
We also discussed marking it as "good first issue". I'm adding the label with "difficulty: medium". The implementation is simple so it should be doable for someone new but will probably require some guidance. |
How would it work if My first impression is that this should be allowed. I would agree that |
I would say it's the same as in the case of non-view/view/pure: If a contract strengthens the requirement in the inheritance graph, all derived contracts must also implement the stronger version. In your example, C must implement it as non-payable. If you declare the function in A as non-payable, then you say that if you are implementing a derived contract that claims to conform to the requirements of A's interface, the function also has to reject all ether transfers.
Why would you say that |
I see... I think this is due to a different interpretation of what payable and non-payable mean. The situation is not exactly the same as non-view/view/pure, because in that case the default is the least strict (non-view), and with non-payable/payable the default is the most strict (non-payable). In my mind,
I don't really have a strong opinion here... Although the motivation to open this issue was so that we could have |
What are your opinions if we add a Because I can see the case of a developer using a library, shadowing a So the rules would be something like:
However, as the current proposal does not solve OZ problem, and I am not aware of any large project that needs this feature, I am not sure it's worth adding complexity here, and we can just keep the existing rules ;) |
Adding a keyword for nonpayable is not necessary. Nonpayable is more restrictive than payable and does not introduce dangers. Therefore overriding from payable to nonpayable will not result in people accidentally getting something more dangerous than they expected. The original issue here is good and should be implemented. Even if "only" OpenZeppelin Contracts and the ERC-721 reference implementation are using this then that should be reason enough to consider this change as impactful. During the ERC-721 standardization process we identified about 30 language design issues (including this) and most were fixed. |
This issue has been marked as stale due to inactivity for the last 90 days. |
unstale |
This issue has been marked as stale due to inactivity for the last 90 days. |
Bump |
This issue has been marked as stale due to inactivity for the last 90 days. |
I nominate this issue to stay open. It is last of the topics written in the text of ERC-721 that has not yet been changed in Solidity. |
This issue has been marked as stale due to inactivity for the last 90 days. |
unstale |
Also just ran into this. Would be great to see support for it. |
This issue has been marked as stale due to inactivity for the last 90 days. |
unstale - let's seriously think about this. Just saw another person run into this issue. |
+1 should be unstale, I have also come across such a use case |
Abstract
If an interface defines a
view
function, it is possible for a derived contract to provide apure
implementation of it.Could it be possible to extend this so that
payable
functions can be implemented with non payable functions? It is the same kind of state mutability narrowing.Motivation
OpenZeppelin/openzeppelin-contracts#2610
ERC721's
transferFrom
is defined as payable in the spec. Our standard implementation is not payable, because if it were payable we would have to define what to do with the message value, which isn't standardized so we don't want to define a specific way to handle it.Because our implementation isn't payable, we've also defined the
interface
as non-payable, but people have pointed out that 1) this is more restrictive than the spec, and 2) there is no way to extend our implementation (through inheritance) to make it payable and add logic to handle msg.value.Specification
A nonPayable function should be a valid implementation of a payable function.
A child contract should be able to extend our nonPayable implementation with a payable function to add a way to handle msg.value before forwarding to
super.transferFrom
.The text was updated successfully, but these errors were encountered: