-
-
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: Try Catch exception handling for External Calls #1517
Comments
I approve this message. I will add this to our next meeting for discussion as well. |
@haydenadams @jacqueswww is Generally, I think it would be good for the purposes of Vyper that only explicit exceptions be "catchable", disallowing something like, with any uncaught exception resulting in a reversion: try:
this.someToken.transfer(a, b, allow_fail=True)
this.call2()
this.call3(allow_fail=True)
except AnyError:
<block of code> |
@jakerockland yes I fully agree, this would be a single built-in Exception for |
Hmm good question. What are some other Vyper exceptions that might be worth catching? |
We don't have other runtime exceptions, except reverting. |
Yeah, I don't see a problem with the only current catchable exception to being |
Though perhaps we do want to allow custom (programmer defined) error types down the road...?, which would make my point more relevant/less abstract 😅 |
My two cents on the matter: if someone is interacting with my contract, it may be nice to be able to pass the error up to the dev utilizing my sc. Chained errors may become more important as protocols start compounding on each other and enable better UX. Agree that could just be a potential down-the-road thing |
I mean personally, I would discourage using this type of behavior over read-only function APIs in my contracts, but I can see utility for this in order to make decisions when executing trades |
This is neat, we should also make the revert reason accessible to the programmer. For clarity, there could be a single exception class named try:
external_contract.foo()
except TransactionReverted as e:
return e.reason (A single exception class is used because there is no way (to my knowledge) to differentiate between a message call failing due to REVERT and failing due to an exceptional halting condition.) Personally I find As an alternative to exception-handling style, we could use error code style, so if |
@fubuloubu the most important usage here is external calls to upgradable addresses such that the upgradable contract can never halt the calling contract through reversion, provided there is a max gas limit on the call. You can't replicate this will read-only. |
Upgradeable contract gotchas strikes again! |
The external call could also be to a non-upgradable contract that has some chance of reverting. In general I think catching errors is super useful considering the async / delayed nature of Ethereum transactions. |
btw would it be possible to catch reversion for an internal call? |
Not really as revert halts the current message call |
Looks like solidity plans to implement this for 0.6 - https://github.com/ethereum/solidity/blob/develop_060/docs/control-structures.rst#trycatch |
Summary
External calls initiated from smart contracts should be allowed to fail without reverting the entire transaction.
Motivation
Catching reversions will increase the flexibility of Vyper and allow experimenting with new smart contract patterns. This is potentially a requirement for Uniswap V2.
The main draw here is you can have a non-upgradable contract that makes external calls to an upgradable contract without the ability for the upgradeable contract to break the non-upgradable contract. This uses a combination of max_gas, mutex, and catching reverts.
Specification
Credit to @jacqueswww for helping out here. It could look something like:
Potentially it could handle multiple calls, not sure:
Backwards Compatibility
Should be fine?
Dependencies
None
Copyright
Copyright and related rights waived via CC0
The text was updated successfully, but these errors were encountered: