-
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
Typed errors / exceptions #7877
Comments
As previously suggested, I've moved the textual changes to a Gist page, that is now to be treated as technical document (not as a blog post), so I can leave in syntax/sema/codegen paragraphs. https://gist.github.com/christianparpart/8dbfafca45306d102eb115485aa48fe3 /cc @chriseth |
@franzihei can you create a blog post out of the gist for the category "feature proposals"? |
We don't have such a category on the blog. We only have:
Maybe "Explainers"? |
Or do you mean we should make it a series, just like with the |
Let's discuss in the meeting if we actually want a blog post pre-release about this. |
Made another writeup: https://hackmd.io/b0vr4MFrSkCLlBEacnds0Q |
This is an interesting proposal! I have a few questions on reading this:
Here's the sort of nasty scenario I'm imagining... imagine two contracts that both define an error with signature Also, I'm guessing But yeah while it maybe has some minor kinks to work out on the whole this seems pretty nice! :) |
They can be defined both in contracts and on the file level. The plan is, as with events, to include in the ABI all errors that can possibly be thrown by the contract, regardless of where they are defined.
I did not plan to change this, so still no error message. This also means that no error message is a "regular" error, not a panic.
That's not clear yet. It might be better to just always put them in the ABI, so that it is also compatible with other languages that choose to have different built-in errors.
Indeed, collisions are a problem. We can warn if two errors with the same signature occur in the same "translation unit" (or even try/catch block), but we cannot detect if an externally-called contract (to which we do not have the source) uses an error with the same signature as one that we have defined. My main question is if there is a big use-case for distinguishing between different errors at the code-level at all, or if this will be mainly used as a user-interface convenience that is much cheaper than error strings. |
Hm, is that the plan for events, or is the plan for events to have a separate |
One still open problem is how to deal with side-effects of the construction of an error:
This should be syntactically valid and I would assume that side-effects of |
Moved from #10922: These are the require statements in the ERC777 implementation of OZ (removed duplicates messages):
With the current syntax, one could create the following errors:
Is there any other option they could do with the current syntax? If we consider having enum datatypes, then we could replace these with:
We could go further and say that errors are actually enum datatypes:
This would generate a function signature of |
In these proposals like |
If we go with something like |
I came around to think that the Basically |
I feel that having both Also, solidity doesn't normally have syntactic sugars, like this |
Since we weren't fully convinced with
|
We more or less came to the conclusion that What is still open is how to properly deal with The first idea was to use One way to make this clearer and also have the syntax for
An different approach is to avoid the use of the
|
[Thoughts from someone who prefers restrictions over convenience for security.] I vote for BTW, in general, I'm concerned about introducing |
I just found #9454 ("Add require(bool,bytes) global function") which seems very relevant to the discussion about |
Isn't that already possible? Shouldn't this already work:
|
Good point. I just checked and it does compile. |
We will proceed with |
Not sure if I'm a bit late with a suggestion like that... but have we ever considered just making errors proper types? I.e.
It would just need to be an alias of
|
Yes, allowing errors to have their own type is a logical extension, but we did not want to go there yet to simplify the implementation. I think evaluation order is still not clarified, because the syntax in the current PR is still possible: |
Yes, |
using require in the following way:
gets complicated because require already does other things, as pointed out. How about instead go for a new keyword?
This seems to be simpler to implement (less upfront changes needed), and seems to provide a cleaner upgrade path for solidity users. Anyway, I think at this point any decision would be better than stalling progress. |
@tfalencar we settled with |
We can probably say that using Errors is best practice and is or will be preferred over revert strings. Also I look forward to a future where Errors can be localized (we can do this entirely in NatSpec). In many (most) use cases,
Here is an example. // SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.8.0; // This error condition is documented, but uses an error string which is not localizable
contract Good {
// @notice This is a really BIG thing
function doThing() external view {
require(tx.origin == address(0), "Only the Devine can execute");
}
} // This error condition is documented and uses localizable errors
contract Better {
// @dev The transaction origin is not devine
error NotGod();
// @notice This is a really BIG thing
function doThing() external view {
if (tx.origin != address(0)) {
revert(NotGod());
}
}
} // This error condition is documented and uses localizable errors
contract Best {
// @dev The transaction origin is not devine
error NotGod();
// @notice This is a really BIG thing
function doThing() external view {
require(tx.origin == address(0), NotGod());
}
} Here is a proposal for a syntactic sugar which solves the two issues above while avoiding the possibility that evaluating the second parameter of I would like to see a differentiation between "simple" error invocations and "complex" invocations. Any error invocation that uses only compile time constant values is "simple". Others are "complex". Now the Test case:require(false, SomeError(tx.origin.call())) will result in "The require function with an error parameter only accepts simple errors. Try using if/revert instead." |
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. |
Add the
error
keyword to specify error / exception types in the same way as events. These errors can then be thrown usingthrow
and they can be used insiderevert
andrequire
causing the 4-byte selector of its type being used for the revert data. The matchingcatch
clause destructures them.Note: For now, we implicitly use the error type
Error(string memory)
and encode its 4-byte selector in the revert data.TODO:
.selector
and.signature
member for errors?try
/catch
for custom errors #11278The text was updated successfully, but these errors were encountered: