@truffle/codec
Version:
Library for encoding and decoding smart contract data
186 lines (185 loc) • 9.34 kB
TypeScript
/**
* # Codec Output Format
*
* ## Module information
*
* This module primarily defines TypeScript types for the output format
* used in results provided by packages
* `@truffle/decoder@>=4.0.0` and `@truffle/codec@>=0.1.0`.
*
* See below for complete listing or continue reading
* [Format information](#format-information) to learn about this format.
*
* ### How to import
*
* Import either as part of Codec or by itself:
*
* ```typescript
* // when importing entire Codec, use Codec.Format.*:
* import * as Codec from "@truffle/codec";
*
* // or import Format directly:
* import { Format } from "@truffle/codec";
* ```
*
* 
*
* ## Format information
*
* This format is intended for use in smart contract and dapp development
* tools and libraries, and for use in display contexts, such as when
* building on-screen components to show transaction and smart contract
* state information.
*
* This format seeks to provide an exhaustive schema for JavaScript
* objects to encode **lossless**, **machine-readable** representations of
* all possible Solidity and ABI data types and all possible values of those
* types.
*
* This format targets types and values understood by the
* [Solidity programming language](https://docs.soliditylang.org/) and
* the [Contract ABI specification](https://docs.soliditylang.org/en/v0.8.19/abi-spec.html),
* within the context of the [Ethereum Virtual Machine](https://ethereum.github.io/yellowpaper/paper.pdf)
* (EVM) and in raw data for transactions and logs according to the
* [Ethereum JSON RPC](https://github.com/ethereum/wiki/wiki/JSON-RPC).
*
* Objects in this format may be deeply nested and/or contain circular
* dependencies. As such, **do not** serialize objects in this format or
* otherwise attempt to display them in full without considering potential
* risk. **Objects in this format are for the machine to read, not humans!**
* This module provides utilities for inspecting objects in this format,
* including the **safe** [[Format.Utils.Inspect.ResultInspector]] wrapper
* (for [util.inspect](https://nodejs.org/api/util.html#util_util_inspect_object_options)),
* and the **unsafe** [[Format.Utils.Inspect.unsafeNativize]] function. For more
* information, please see the documentation for those utilities.
*
* ### Specification
*
* Individual decoded values are represented by objects of the type
* [[Format.Values.Result]], which contain the following fields:
* 1. `type`: This is a [[Format.Types.Type|`Type`]] object describing the value's
* type. Each `Type` has a `typeClass` field describing the overall broad type,
* such as `"uint"` or `"bytes"`, together with additional information that gives
* the specific type. For full detail, see [[Format.Types]].
*
* 2. `kind`: This is either `"value"`, in which case the `Result` is a
* [[Format.Values.Value|`Value`]], or `"error"`, in which case the `Result` is an
* [[Format.Errors.ErrorResult|`ErrorResult`]]. In the former case, there will be
* a `value` field containin the decoded value. In the latter case, there will be
* an `error` field indicating what went wrong. *Warning*: When decoding a
* complex type, such as an array, mapping, or array, getting a kind of `"value"`
* does not necessarily mean the individual elements were decoded successfully.
* Even if the `Result` for the array (mapping, struct) as a whole has kind
* `"value"`, the elements might still have kind `"error"`.
*
* 3. `value`: As mentioned, this is included when `kind` is equal to `"value"`.
* It contains information about the actual decoded value. See
* [[Format.Values|`Format.Values`]] for more information.
*
* 4. `error`: The alternative to `value`. Generally includes information about
* the raw data that led to the error. See [[Format.Errors|`Format.Errors`]] for
* more information.
*
* 5. `interpretations`: This field will also be present when `kind` is equal
* to `"value"`; it is an object that may contain additional information
* about the decoded value beyond what is found in `value`. (All fields in
* `interpretations` are always optional and will be included only when
* applicable.) You may wonder, what is the difference between `value`
* and `interpretations`? The answer is that the distinction is largely
* historical; `interpretations` was not originally part of the format, and
* it was added so that there would be a place to put new additional
* information we wanted to include without having to expand `value`. See
* [[Format.Values|`Format.Values`]] for more information.
*
* 6. `reference`: This field is a debugger-only feature and does not
* apply to results returned by @truffle/decoder, so it won't be documented here.
*
* ### Values vs. errors
*
* It's worth taking a moment here to answer the question: What counts as a value,
* and what counts as an error?
*
* In general, the answer is that anything that can be generated via Solidity
* alone (i.e. no assembly), with correctly-encoded inputs, and without making use
* of compiler bugs, is a value, not an error. That means that, for instance, the
* following things are values, not errors:
* - A variable of contract type whose address does not actually hold a
* contract of that type;
* - An external function pointer that does not correspond to a valid
* function;
* - A string containing invalid UTF-8;
* - ..., etc.
*
* By contrast, the following *are* errors:
* - A `bool` which is neither `false` (0) nor `true` (1);
* - An `enum` which is out of range;
* - ..., etc.
*
* (You may be wondering about the enum case here, because if you go sufficiently
* far back, to Solidity 0.4.4 or earlier, it *was* possible to generate
* out-of-range enums without resorting to assembly or compiler bugs. However,
* enums are only supported in full mode (see
* [Notes on decoding modes](../#decoding-modes)),
* which only supports 0.4.12 and later, so
* we consider out-of-range enums an error. There are also additional technical
* reasons why supporting out-of-range enums as a value would be difficult.)
*
* There are three special cases here that are likely worthy of note.
*
* Firstly, internal function pointers currently can't be meaningfully
* decoded via @truffle/decoder. However, they decode to a bare-bones value,
* not an error, as it is (in a sense) our own fault that we can't decode
* these, so it doesn't make sense to report an error, which would mean that
* something is wrong with the encoded data itself. This value that it
* decodes to will give the program counter values it corresponds to, but
* will not include the function name or defining class, as @truffle/decoder
* is not presently capable of that. For now, full decoding of internal
* function pointers remains a debugger-only feature. (But limited support for
* this via @truffle/decoder is planned for the future.)
*
* (When using the debugger, an invalid internal function pointer will decode to an
* error. However, when using @truffle/decoder, we have no way of discerning whether
* the pointer is valid or not, so internal function pointers will always decode to
* a value, if an uninformative one.)
*
* Secondly, when decoding events, it is impossible to decode indexed parameters
* of reference type. Thus, these decode to an error
* (`IndexedReferenceTypeError`, which see) rather than to a value.
*
* Thirdly, the decoder is currently limited when it comes to decoding state
* variables that are declared constant, and not all such variables are yet
* supported in decoding; attempting to decode one of these that is not currently
* supported will yield an error.
*
* Similarly, there are various things that decode to errors for technical reasons.
* Objects with encoded length fields larger than what fits in a JavaScript safe
* integer, or pointed to by pointers with values larger than what fits in a
* JavaScript safe integer, will decode to errors, even if they may technically be
* legal. Such cases are impractical to handle and should never come up in real
* use so we decode them to errors. Errors may also be returned in case of an
* error in attempting to read the data to be decoded.
*
* Finally, except when decoding events, we do not return an error if the pointers
* in an ABI-encoded array or tuple are arranged in a nonstandard way, or if
* strings or bytestrings are incorrectly padded, because it is not worth the
* trouble to detect these conditions.
*
*
* ## Notes on this documentation
*
* Most of this doesn't have explanatory documentation
* because it's largely self-explanatory, but particularly
* non-obvious parts have been documented for clarity.
*
* A note on optional fields: A number of types or values
* have optional fields. These contain helpful
* but non-essential information, or information which
* for technical reasons we can't guarantee we can determine.
*
* @category Data
*
* @packageDocumentation
*/
import { Types, Values, Errors } from "./common";
import * as Utils from "./utils";
export { Types, Values, Errors, Utils };