If I make a request to get events in a particular block using web UI, I get a nice human-readable response:

enter image description here

I've made an RPC call to get the same data

    "id": 1,
    "jsonrpc": "2.0",
    "method": "state_getStorageAt", 
    "params": ["0x26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7","0x5056c4cb701e192962e5a76c895273e69188edea1badf9b145b884a9416c8443"]

... and I got an output

    "jsonrpc": "2.0",
    "result": "0x1000000000000000585f8f090000000002000000010000000508ba6ef6480a2c4173bbbf0c27355c0e3c6d7a874a21cc2464e97d3fd5d92e245b1b5a7307000000000000000000000000000001000000080380eb30ca364f5c349d573b62cfadadba95af2e94f62fd8af4e15b90b971a4da633803b0648373051a1e2158c547112dcf63802d0d52b301a33dae8b9c6114e90f012b8516d57525358775a7476385956586574346e43424a396776646d4a6e3564364b34385a6a6148704763515a75676300000100000000001027000000000000000000",
    "id": 1

I understand that it is a set of data encrypted with SCALE codec.

For example 0803 is a pallet and method indexes and eb30ca364f5c349d573b62cfadadba95af2e94f62fd8af4e15b90b971a4da633 is attached data.

What is the best way to decode the complete result with Rust? Thanks


In the end this worked for me

#[subxt::subxt(runtime_metadata_path = "metadata.scale")]
pub mod polkadot {}

let data = "0x0c00000000000000585f8f090000000002000000010000000508ba6ef6480a2c4173bbbf0c27355c0e3c6d7a874a21cc2464e97d3fd5d92e245bd859730700000000000000000000000000000100000000010308011027000000000000000000";
let data_bytes = hex::decode(data.replace("0x", "")).unwrap();
let event = <polkadot::system::storage::Events as StorageEntry>::Value::decode(&mut data_bytes.as_slice()).unwrap();

1 Answer 1


There's two ways of decoding events in rust: statically typed and dynamically typed.

Statically you can use subxt to decode events from this SCALE encoding - it's done here for example. Basically every runtime has a concrete Event type and that's what you're decoding into.

let event_bytes = hex::decode("0x1000000000000000585f8f090000000002000000010000000508ba6ef6480a2c4173bbbf0c27355c0e3c6d7a874a21cc2464e97d3fd5d92e245b1b5a7307000000000000000000000000000001000000080380eb30ca364f5c349d573b62cfadadba95af2e94f62fd8af4e15b90b971a4da633803b0648373051a1e2158c547112dcf63802d0d52b301a33dae8b9c6114e90f012b8516d57525358775a7476385956586574346e43424a396776646d4a6e3564364b34385a6a6148704763515a75676300000100000000001027000000000000000000").unwrap();
let event = <polkadot::Event as Decode>::decode(&mut event_bytes.as_slice()).unwrap();

and I have polkadot defined as:

#[subxt::subxt(runtime_metadata_path = "polkadot_metadata.scale")]
pub mod polkadot {}

(rather than pointing it at a metadata file you can download it by giving it a url #[subxt::subxt(runtime_metadata_path = "wss://kusama-rpc.polkadot.io:443")]. If you point that at your node's url then it should decode your event.)

Dynamically the tooling needs generalising, but it is possible and has been done by cargo-contract.

If you need to interpret all events across all parachains then go dynamic. If you are focused on a few particular parachains then static typing is a lot safer and easier.

  • Thanks for the answer. Is there an option to decode it using parity_scale_codec::Decode? If I understand correctly Decode is just a Trait and I need pre-defined Struct to use it. Where can I find the structure of an event? Commented May 17, 2022 at 7:41
  • 1
    The above are all using that Decode trait but the key is that you need to give it the type to re-hydrate (to deserialise into). That's the Event type that is defined on the runtime associated with the parachain / relay chain that your decoding the event for.
    – Squirrel
    Commented May 18, 2022 at 8:55
  • Thanks for your help. My solution was based on your answer Commented Aug 2, 2022 at 12:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.