-
-
Notifications
You must be signed in to change notification settings - Fork 804
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: syntactic distinction for external vs internal calls #2856
Comments
meeting notes: approved, use |
another even more exotic thought -- we could have all external fns be declared with this starts to break down a bit though because in python, |
Definitely don't care for 'await' being used in this regard because it strongly infers asynchronous semantics which are not present in the EVM. 'call' or 'send' (as in sending a msg to another actor/contract entity) seem closer semantically to me. I would also suggest that some variant of this could be used to represent delegate-style calls possibly but I obviously haven't thought that one through all the way. |
Hello, maybe I'm a bit late to the party but I think it would be worth considering other naming possibilities rather than the |
another idea for the keyword (from kotlin) - |
How about |
I also dislike I think we both want to mark the call and also make the distinction between jmp and call explicit - as such I prefer keyword variants with I like either |
What about just |
just tried out a few different options, and |
after trying out rewriting some test contracts, it seems that a further differentiation between |
this was implemented in #2938 |
Simple Summary
Add a syntactic distinction between internal and external calls. This could be in the form of a keyword, e.g.
await SomeInterface(msg.sender).foo()
. The keyword could also becall
.Motivation
Internal and external calls have very different semantics. External calls invoke the
CALL
opcode and pass execution context to another (probably untrusted) contract, while internal calls are "safe" in that they justJUMP
around the local contract. This is already reflected in the semantics of internal vs external calls, for instance external calls support the keywordsgas=, value=, skip_contract_check=, default_return_value=
, which are not supported for internal calls.Right now, it is relatively easy to tell visually whether a function call is an internal or external call, as internal calls will all use the
self
namespace (e.g.self.foo()
, as opposed toself.bar.foo()
). However, as we move towards a more complex module system in vyper (cf. #1954, #2431), it will become more difficult to tell at a glance whether any given call is internal or external, and will require referencing the definition of a function to determine if it is internal or external. This seems to go against vyper's goal of readability/auditability. It would also help the author of a contract, as it forces them to consider the consequences every time they call to an external contract. External calls are expensive to reason about, and the syntax should reflect that! Lastly, this VIP makes it easier to find all external calls made by a contract (which might be done during code review, audit or vulnerability scanning), as it can be done with simple text search.This VIP proposes the use of the
await
keyword to signal that a call is external. This keyword is already familiar to Python programmers, and fits well withawait
's cooperative multitasking semantics - "this will pass execution control to something else, and we may get control back after it returns".Potential Drawbacks
A drawback of this VIP is that it introduces a code reusability concern. For instance, if
HelperContract
is initially implemented as an internal module, called as followsbut then later due to code size issues, needs to be factored out into a separately deployed contract, any usages like the above would need to be changed to
This might be annoying to do. But, maybe this is a feature, not a bug(!), in that it forces the programmer to be explicit about the scope and execution context of the helper contract.
Specification
Calls to external contracts are required to be prefixed with the
await
keyword. If it is not (or, conversely, if a call to an internal module is prefixed withawait
), a semantic or typechecker error should be thrown.Backwards Compatibility
Users will need to syntactically update every call to an external contract.
Dependencies
References
#1954, #2431
Copyright
Copyright and related rights waived via CC0
The text was updated successfully, but these errors were encountered: