You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Instead of throwing opaque string reverts, 3.0 contracts will instead throw custom, ABI-encoded "rich" revert types augmented with much more useful parameters.
Motivation
Reverting with expressive error data will enable developers to create more robust applications built on top of the 0x protocol.
Additionally, this is a critical step towards our goal of becoming a language-agnostic protocol, wherein applications can rely more on the contracts themselves and less on off-chain tooling to validate and debug interactions.
Specification
Encoding
Standard string reverts (à la Soldity's require() and revert() builtins) are ABI-encoded as a function call with signature Error(string).
For example, a revert("foobar") would encode as:
# 4-byte function selector (keccak of "Error(string)")08c379a0# Offset to the error string calldata.0000000000000000000000000000000000000000000000000000000000000020# -> Error string data# Length of string (6)0000000000000000000000000000000000000000000000000000000000000006# String bytes0000000000000000000000000000000000000000000000000000666f6f626172
Our rich reverts follow the same encoding rules but with varying function signatures.
For example, the rich revert SignatureError has the signature:
# 4-byte function selector (keccak of "SignatureError(uint8,bytes32,address,bytes)")7e5a2318# errorCode, padded to 32-bytes0000000000000000000000000000000000000000000000000000000000000003# Signature hasha3dcd8f6179b531a8c33b675b700708090d4e94d6f6f4cd9e652239a6225db45# Offset to signature bytes data0000000000000000000000000000000000000000000000000000000000000060# -> Signature bytes data# Length of bytes (66)0000000000000000000000000000000000000000000000000000000000000042# bytes data010aeaf352d05c6dcf64882760014703432133689f4507cd91e81aaa3b289223507bc8cf2629ff3ea8a468013a49b32227900be174575ce135ed2560c236dba68802
Decoding
Nodes will only return revert data for eth_call operations, though it is possible (but not foolproof) to replay a failed transaction using eth_call and a block number.
Furthermore, with geth there is an issue where the JSON-RPC response for a successful eth_call is indistinguishable from a revert. For this reason, (at minimum) we need to check the leading 4 bytes of the return data against a mapping of known error selectors to detect that a revert actually occurred. This is a little inelegant, but with roughly 4 billion combinations of leading 4 bytes, combined with more rigorous conformance checks, false positives should be extremely rare.
Once the exact error type is detected, ABI decoding tools can be used to extract individual parameter values.
For environments where ABI decoding tools are not exposed/available, we will also be deploying a helper contract that decomposes encoded error bytes into its constituent fields.
Proposed Error Types
Thus far, we propose the following rich revert types:
Summary
Instead of throwing opaque string reverts, 3.0 contracts will instead throw custom, ABI-encoded "rich" revert types augmented with much more useful parameters.
Motivation
Reverting with expressive error data will enable developers to create more robust applications built on top of the 0x protocol.
Additionally, this is a critical step towards our goal of becoming a language-agnostic protocol, wherein applications can rely more on the contracts themselves and less on off-chain tooling to validate and debug interactions.
Specification
Encoding
Standard string reverts (à la Soldity's
require()
andrevert()
builtins) are ABI-encoded as a function call with signatureError(string)
.For example, a
revert("foobar")
would encode as:Our rich reverts follow the same encoding rules but with varying function signatures.
For example, the rich revert
SignatureError
has the signature:If we construct it with the following values:
The resulting encoding will be:
Decoding
Nodes will only return revert data for
eth_call
operations, though it is possible (but not foolproof) to replay a failed transaction usingeth_call
and a block number.Furthermore, with geth there is an issue where the JSON-RPC response for a successful
eth_call
is indistinguishable from a revert. For this reason, (at minimum) we need to check the leading 4 bytes of the return data against a mapping of known error selectors to detect that a revert actually occurred. This is a little inelegant, but with roughly 4 billion combinations of leading 4 bytes, combined with more rigorous conformance checks, false positives should be extremely rare.Once the exact error type is detected, ABI decoding tools can be used to extract individual parameter values.
For environments where ABI decoding tools are not exposed/available, we will also be deploying a helper contract that decomposes encoded error bytes into its constituent fields.
Proposed Error Types
Thus far, we propose the following rich revert types:
Error(string message)
0x08c379a0
SignatureError(uint8 errorCode, bytes32 hash, address signer, bytes signature)
0x7e5a2318
BadSignature
InvalidLength
Unsupported
Illegal
InappropriateSignatureType
SignatureValidatorError(bytes32 hash, address signer, bytes signature, bytes errorData)
0x169fad8c
SignatureType.Validator
.SignatureWalletError(bytes32 hash, address wallet, bytes signature, bytes errorData)
0x1b8388f7
SignatureType.Wallet
.SignatureOrderValidatorError(bytes32 hash, address signer, bytes signature, bytes errorData)
0xfabf4577
SignatureType.OrderValidator
.SignatureWalletOrderValidatorError(bytes32 hash, address wallet, bytes signature, bytes errorData)
0xa85f3360
SignatureType.WalletOrderValidator
.OrderStatusError(uint8 currentStatus, bytes32 orderHash)
0x2992a71c
OrderEpochError(address maker, address sender, uint256 currentEpoch)
0x4ad31275
InvalidSenderError(bytes32 orderHash, address sender)
0x95b59997
InvalidTakerError(bytes32 orderHash, address taker)
0xfdb328be
InvalidMakerError(bytes32 orderHash, address maker)
0x26bf55d9
FillError(uint8 errorCode, bytes32 orderHash)
0xe94a7ed0
InvalidTakerAmount
TakerOverpay
Overfill
InvalidFillPrice
AssetProxyDispatchError(uint8 errorCode, bytes32 orderHash, bytes assetData)
0x488219a6
InvalidAssetDataLength
UnknownAssetProxy
AssetProxyTransferError(bytes32 orderHash, bytes assetData, bytes errorData)
0x4678472b
transfer()
reverting)NegativeSpreadError(bytes32 leftOrderHash, bytes32 rightOrderHash)
0xb6555d6f
matchOrders()
IncompleteFillError(bytes32 orderHash)
0x152aa60e
matchOrders()
TransactionError(uint8 errorCode, bytes32 transactionHash)
0xf5985184
NoReentrancy
AlreadyExecuted
TransactionSignatureError(bytes32 transactionHash, address signer, bytes signature)
0xbfd56ef6
TransactionExecutionError(bytes32 transactionHash, bytes errorData)
0x20d11f61
fillOrKill()
.AssetProxyExistsError(address proxy)
0xcc8b3b53
The text was updated successfully, but these errors were encountered: