Attackathon _ Fuel Network 32979 - [Smart Contract - Low] operations with StorageVec incorrectly rev
Last updated
Was this helpful?
Last updated
Was this helpful?
Submitted on Mon Jul 08 2024 18:21:13 GMT-0400 (Atlantic Standard Time) by @cyberthirst for
Report ID: #32979
Report type: Smart Contract
Report severity: Low
Target: https://github.com/FuelLabs/sway/tree/v0.61.2
Impacts:
Permanent freezing of funds
Certain operations with StorageVec
can revert. The type StorageVec
has 0 size (due to optimization reasons when manipulating storage). The 0 size is, however, problematic because some functions in lib-std
assume the invariant that types they operate on are non-zero. Because this invariant is broken, the functions revert.
The StorageVec
is defined as pub struct StorageVec<V> {}
, and the type has 0 size. Certain functions in lib-std
like load_vec
in storage_vec.sw
take the size of the inner type via let size_V_bytes = __size_of::<V>();
and perform further computations with the size.
So if we have eg a StorageVec<StorageVec<u64>
then the inner type has 0 size. If we call load_vec
on such nested storage vec, then the code will revert:
This is because the type size is 0, and thus, we didn't allocate any memory (because len_bytes
will evaluate to 0). But when the nested vec has a non-zero len
, then copy_bytes_to
will revert due to the access of unallocated memory.
The PoC shows that if the nested StorageVec
is used in a withdraw
function, then the funds can be permanently blocked because the code would always revert.
However, using nested vectors is rather an unlikely pattern in smart contracts and as such we rate it with low
impact.
The whole PoC is provided as a zip in Google Drive: https://drive.google.com/file/d/1ExpSThwZ3jk5SrUM664wMCC_qo6v--cP/view?usp=sharing
Unzip the archive and run forc test
.
The PoC demonstrates that the operations on the nested storage vector incorrectly revert and might cause blocking of user funds: