intrepidshape/elm-web3/3.0.0

Web3.Abi.Decode

Helpers to decode contract return values from JSON received through ports from the JS Web3 layer.

address : Decoder Address

Decode an Address return value.

uint256 : Decoder BigInt

Decode a uint256 return value as a BigInt. Accepts both decimal strings ("100") and 0x-prefixed hex strings ("0x64").

int256 : Decoder BigInt

Decode an int256 return value as a BigInt.

Accepts a decimal string (already signed, as the JS bridge sends it) or a 0x-prefixed 32-byte hex word, which is interpreted as two's complement.

-- 0xffff..ff is -1, not 2^256-1
decodeString int256 "\"0xffff...ffff\"" == Ok (BigInt.fromInt -1)
bool : Decoder Bool

Decode a bool return value.

string : Decoder String

Decode a string return value.

bytes32 : Decoder String

Decode a bytes32 hex string (e.g. an event topic). Expects a 0x-prefixed 66-character hex string and returns it as-is.

uint8 : Decoder Int

Decode a uint8 return value as an Elm Int (validated 0-255).

uint16 : Decoder Int

Decode a uint16 return value as an Elm Int (validated 0-65535).

uint32 : Decoder Int

Decode a uint32 return value as an Elm Int (validated 0-4294967295).

uint64 : Decoder BigInt

Decode a uint64 return value as a BigInt (exceeds JS/Elm safe Int range).

uint128 : Decoder BigInt

Decode a uint128 return value as a BigInt.

hexSlot : Int -> String -> String

Extract the 64-character hex of the 32-byte word at slot index n (0-indexed) from a 0x-prefixed ABI-encoded hex string.

hexSlot 0 "0x0000...0064" == "0000...0064"
uint256Slot : Int -> String -> Maybe BigInt

Decode a uint256 from slot n of a raw 0x-hex ABI response.

int256Slot : Int -> String -> Maybe BigInt

Decode an int256 from slot n of a raw 0x-hex ABI response.

The signed counterpart of uint256Slot. Use this for any value Solidity declares as int* -- ticks, funding rates, PnL, rebase deltas. Reading those with uint256Slot yields a number near 2^256 instead of a small negative one.

addressSlot : Int -> String -> Maybe Address

Decode an Address from slot n of a raw 0x-hex ABI response. Addresses are right-aligned in the 32-byte slot.

boolSlot : Int -> String -> Maybe Bool

Decode a bool from slot n of a raw 0x-hex ABI response.

stringSlot : Int -> String -> Maybe String

Decode a dynamic UTF-8 string from slot n of a raw 0x-hex ABI response. Slot n contains an offset pointer; the string length and data follow at that offset.

listSlot : Int -> (Int -> String -> Maybe a) -> String -> Maybe (List a)

Decode a dynamic array from slot n. Each element is decoded by calling elemDecoder slotIndex fullHex. Works for static-element arrays (uint256[], address[], etc.) where elements are stored consecutively.

(Int -> String -> Maybe a)
-> (Int -> String -> Maybe b)
-> String
-> Maybe ( a, b )

Decode a static 2-tuple from the head of a 0x-hex ABI response. Each decoder is called with its slot index (0, 1).

(Int -> String -> Maybe a)
-> (Int -> String -> Maybe b)
-> (Int -> String -> Maybe c)
-> String
-> Maybe ( a, b, c )

Decode a static 3-tuple from the head of a 0x-hex ABI response.

decodeRevertReason : String -> Maybe String

Attempt to decode an EVM revert reason from raw revert data.

Checks for the Error(string) selector 0x08c379a0 and decodes the ABI-encoded string that follows. Returns Nothing if the data is not a standard Error(string) revert.

decodeRevertReason "0x08c379a000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000012496e73756666696369656e742066756e64730000000000000000000000000000"
--> Just "Insufficient funds"
List
{ selector : String
, name : String
, decodeArgs : String -> Maybe (List String)
}
-> String
-> Maybe
{ name : String
, args : List String
}

Decode a typed Solidity custom error (error InsufficientBalance(uint256 have, uint256 want)) from raw revert data, given selector fragments the app bakes at codegen time -- the same no-runtime-keccak philosophy as Web3.Abi.Calldata selectors.

fragments =
    [ { selector = "cf479181"      -- keccak("InsufficientBalance(uint256,uint256)")[:4]
      , name = "InsufficientBalance"
      , decodeArgs = \tail -> Maybe.map2 (\a b -> [ a, b ])
            (word 0 tail) (word 1 tail)
      }
    ]


decodeCustomError fragments revertData
--> Just { name = "InsufficientBalance", args = [ "5", "10" ] }

decodeArgs receives the ABI-encoded argument tail as bare hex (no 0x, selector already stripped) and renders each argument to a display string -- build it from this module's slot readers.

Precedence, decided: this function REFUSES the standard selectors 08c379a0 (Error(string)) and 4e487b71 (Panic(uint256)) so it composes with decodeRevertReason unambiguously in either order -- each decoder has a disjoint domain.

Returns Nothing for: standard selectors, unknown selectors, payloads shorter than a selector, or a fragment whose decodeArgs fails.