The general format for extrinsics are -
- length of extrinsic as a
Compact<u32>
- version byte + signed flag
- sender address (only included if signed, as per flag above)
- sender signature (only included if signed, as per flag above)
- additional signed extension values as per metadata (only included if signed, as per flag above)
- pallet index for call (as per metadata)
- method index for call (as per metadata)
- call data (as per metadata types)
Decoding the 0x280402000b919bbc3b8001
extrinsic manually, i.e. with a manual lookup against what we know the metadata to be -
28
first byte, as per the format above it is the compact length. Since lower 2 bits are 0b00
, we know the data here is contained in a single byte. So in this case 40 >> 2
(decimal, shifting as per rules for 0b00
) yields 10 bytes in length for the extrinsic (this excludes the length prefix, only the data bytes are counted)
04
is next, containing the version byte + signed flag. The top-most bit is unset, this means the transaction is unsigned. In this case 04
determines the extrinsic version
Since we now determined it is unsigned with the version byte, here we skip the decoding of address, signature & signed extensions, and jump straight into the call part -
02
the pallet index (on Kusama this is timestamp
, it will be different for other chains and could possibly change between upgrades)
00
the call index inside the pallet (on Kusama this points to timestamp.set
for the current metadata, can also change when upgraded)
The variable call data therefore is the remaining 0b919bbc3b8001
. As per the metadata for this call on the current Kusama runtime, this is a single Compact<u64>
representing now
. Looking at the first byte, 0b
(hex), this is 0b0000_1011
in binary, the lower two bits are both set, which means this byte contains the length of the data to follow. (00
, 01
and 10
has different rules)
Converting this, we know 0b
(hex) is 11
in decimal, where the length of the data would therefore be (11 >> 2) + 4
bytes following for this type of flag, i.e. a calculated 6 bytes data should follow this indicator, all containing the data.
So this is a simple form of compact encoding, no additional shifting is needed and we can simply convert the remaining 6 bytes into LE u64
. The next 6 bytes 919bbc3b8001
(all the remaining data) is [145, 155, 188, 59, 128, 1]
in base-10 array form. Converting this to LE (once again manually, sticking with the approach followed thus far) -
(((((((((1 * 256) + 128) * 256) + 59) * 256) + 188) * 256) + 155) * 256) + 145 = 1650269658001
Converting to to unix epoch time this represents Mon Apr 18 2022 08:14:18 GMT+0000