Smart contracts using Anchor require developers to allocate space for new accounts and specify the account size. Anchor provides guidelines for calculating the size based on the account structure, but many developers use std::mem::size_of instead, as they don’t have to manually update the size when making changes to the account structure. Are they equivalent? In this blog post, we conduct a systematic comparison of the results produced by std::mem::size_of and the Anchor space reference.
While std::mem::size_of generally works well and allocates more space than necessary, there are some scenarios where it may return a smaller size. Therefore, developers should understand the differences between these two methods before selecting the appropriate method.
In Anchor, developers commonly utilize std::mem::size_of<T>() to determine the size of the Account struct. However, this function may not produce an exact match with the size of the data stored in the Account after serialization with BorshSerialize.
The table below provides a summary of the size calculation for different data types using both methods. While most types give the same results, discrepancies may arise for certain data types, such as Vector and Enum, where std::mem::size_of<T>() may return a smaller value.
Note: all experiments in this blog post were done on a 64-bit machine.
The size_of function in Rust returns a fixed value based on the size information of the type and may not provide an accurate calculation of the memory occupied for some objects.
When calculating the size of the Example account that contains a vector of type T, some developers may use the formula std::mem::size_of::<Example>() + (std::mem::size_of::<T>() * example.len()).
This approach is valid and may even result in an account size that exceeds the original structure size of 20 bytes, because after serialization with BorshSerialize, the content of the vector becomes the length (4 bytes) plus the size of the actual content.
Please note that it is necessary to account for the additional bytes required to store the length of the vector when calculating the total account size.
The Option<T> has two variants: None or Some. In memory, the None variant doesn't store any values but just a "tag" of 0, while the Some variant stores values together with the "tag" of 1.
However, the 0/1 "tag" is not needed if T is a Box or other smart pointer types. Since smart pointers in Rust cannot be 0, None can be represented as 0 and Some can be directly represented by the value of the pointer itself.
Therefore, when calculating the size of an Option<T> using the size_of function, the result will depend on the type T:
In comparison, after serialization, the actual space occupied is 1 + space(T), because Option uses 1 byte to represent Some or None.
Typically, when the size_of function is applied to an enum, the result equals to the space of the discriminant plus the space of the largest variant, taking into account the proper memory alignment padding.
In Rust, the size_of function returns a fixed value based on the size information of a given type, but it may not accurately calculate the memory occupied by the object.
Therefore, when calculating the size of an account, it is important to note that using the size_of function may lead to inconsistencies between the calculated size and the actual size of the account. To ensure accuracy, it is recommended to manually calculate the account size using the corresponding value from the official Anchor documentation.
sec3 is a security research firm that prepares Web3 projects for millions of users. The Launch Audit is a rigorous, researcher-led code examination that investigates and certifies mainnet-grade smart contracts; sec3’s continuous auditing software platform, X-ray, integrates with Github to progressively scan pull requests, helping projects fortify code before deployment; and sec3’s post-deployment security solution, WatchTower, ensures funds stay safe. sec3 is building technology-based scalable solutions for Web3 projects to ensure protocols stay safe as they scale.
To learn more about sec3, please visit https://www.sec3.dev