Serialisation

While storage on NEAR is pretty cheap (100kb/1 NEAR), it’s not so cheap we should waste it. When sending data across the Internet, JSON is the de-facto standard format. However, it isn’t a very good representation for smart contract state: it isn’t very efficient, and it’s not strictly typed. Therefore, for internal state representation, NEAR uses Borsh.

Borsh

Borsh stands for Binary Object Representation Serializer for Hashing. It is meant to be used in security-critical projects as it prioritizes consistency, safety, speed; and comes with a strict specification.

It optimizes for the following qualities in the decreasing priority:

  • Consistency - there is a bijective mapping between objects and their binary representations. There is no two binary representations that deserialize into the same object. This is extremely useful for applications that use binary representation to compute hash.

  • Safety - Borsh implementations use safe coding practices. In Rust, Borsh uses almost only safe code, with one exception to avoid exhaustion attack.

  • Specification - Borsh comes with a full specification that can be used for implementations in other languages.

  • Speed - In Rust, Borsh achieves high performance by opting out from Serde which makes it faster than bincode in some cases; which also reduces the code size;

Borsh serialization is all well and good for internal representation, but it’s hardly a web-friendly representation. Therefore, the #[near_bindgen] macro intelligently converts function return values into JSON before sending the response back to the node. It does this using serde.

This means that one smart contract is usually dealing with data in at least three forms:

  • Native, in-memory

  • JSON

  • Borsh

Last updated