-
Notifications
You must be signed in to change notification settings - Fork 430
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
Contract output on reverted executions #1841
Comments
Alternatively: There isn't even a need to change the metadata at all to make this work. If we just specify that front-ends and calling contracts always must decode the |
Result
and revertsResult
vs. revert flag
Result
vs. revert flag
The An example is the Another example is the Yeah, the examples use removed |
I see why contracts want to return errors. But I'm still not convinced that a contract output can be the same in the revert case and in the non-revert case. This is strongly reflected in |
I'm not saying that the output is the same in the revert and non-revert cases. It is clear that in the non-revert case, the output is only The problem in your proposal comes with:
We need to propagate errors from ink! auto-generated code to the end-user. It means that the message's defined type enum CombinedErrorForMessageX {
UserError(UserError),
LangError(LangError),
} But it is the same in terms of performance because you spend one byte to make the difference between I also want to highlight that we create/return |
Right now, #[non_exhaustive]
enum RevertReason<T> {
ContractReverted(T), // Holding whatever the contract message returns if it decides to revert.
SelectorInvalid,
/// maybe more in the future
} How does this generic type increase contract sizes and create "weird" types in the metadata, when we already have nested generic types as the contract outputs? |
However, seems like for now I don't even need such breaking changes to the metadata. We have the language in the metadata for a reason. For my use case it'd most likely be sufficient to specify that for Solang Solidity contracts, the contracts only return their message return type if they didn't revert. Otherwise, the output will be the a standartd Solidity error and the |
Yeah, you are right. I forgot that we can define generic type on ink! level instead defining it for each output(like Hmm, this feature should be implemented in this way initially based on the issue. I remember we discussed it here. And the final decision was to have one @HCastano Was there any reason why you selected the approach with two |
Ah that is a good find. Well I think in #1207 and following discussions and PRs were solving a (very slightly) different problem; namely allowing to include something like language errors in the Metadata. And we just now started talking about whether it makes sense at all to "allow" ink! contracts to revert and return I mean for example before #1446 we didn't have fallible constructors. Things like this might have played a role in designing the metadata in regards to the language error. |
@xermicus what's the status of this issue? |
@SkymanOne to me the question as to why the contract execution output is wrapped inside a After all, if the metadata would allow to explicitly specify distinct return types for revert and non-revert execution outputs, it'd allow languages without the |
To me it makes sense that there are two layers of This is similar to how you can have different error types when interacting with a REST service:
In my experience, bundling all of these (otherwise unrelated) concepts together just makes it harder to the other side. |
On a more serious note. I'm not questioning the concept of a I mean if there are dedicated types for reverted and non-reverted executions, you can still have |
@xermicus I cannot comment on internals of the pallet contracts, I'm not that familiar with it yet at the moment. I'm talking about a general approach for "signalling" and handling errors. It's pretty common in IT to have different "channels" for different domains - separation of concerns. Although, now that I think of it again, I think I've misinterpreted the "inner" |
As per the docs, returning an
Err
from a message will always revert the contract execution. Now that makes me wondering as to whyink!
contracts always return aMessageResult
, instead of the actual type?Given that:
Ok
will never revert the executionErr
will always revert the executionUnless I'm missing something here, it does seem unnecessary to always encode the contract output as a
Result
; this is known anyways based on the revert flag. Additionally, the current model implies that we need to support situations where a contract would returnErr
but not revert it's state and vice versa, and I'm not sure when that would be useful.I think the whole situation could be simplified by defining that:
O
andE
as their outputO
is expected if the execution did not revertE
is expected if the execution did revertWhich would:
ink!
metadata. There would be no need do define a "special"LanguageError
type or wrapping the message ouptuts in nested types likeMessageResult
. Instead, each contract message would just define theirO
andE
types.Result
types at runtime. Yes it's only 1 or 2 bytes but why not getting rid of any redundancy we can. Requiring all contracts to always encode their message results prefixed with 1 or 2 bytes, which encode no meaningful (because redundant) data, just becauseink!
does expect that, signals inelegance.Result
type.Of course, this would be a major breaking change requiring careful consideration.
The text was updated successfully, but these errors were encountered: