Generation of storage addresses seemingly can lead to an out-of-range panic
temyurchenko opened this issue · comments
In crates/cairo-lang-starknet/src/plugin/storage.rs
, function handle_legacy_mapping_storage_var
generates Cairo logic for computing addresses:
/// Generate getters and setters skeleton for a non-mapping member in the storage struct.
fn handle_legacy_mapping_storage_var(address: &str) -> String {
format!(
"
mod $storage_var_name$ {{$extra_uses$
use starknet::SyscallResultTrait;
use starknet::SyscallResultTraitImpl;
fn address(key: $key_type$) -> starknet::StorageBaseAddress {{
starknet::storage_base_address_from_felt252(
hash::LegacyHash::<$key_type$>::hash({address}, key))
}}
fn read(key: $key_type$) -> $value_type$ {{
// Only address_domain 0 is currently supported.
let address_domain = 0_u32;
starknet::StorageAccess::<$value_type$>::read(
address_domain,
address(key),
).unwrap_syscall()
}}
fn write(key: $key_type$, value: $value_type$) {{
// Only address_domain 0 is currently supported.
let address_domain = 0_u32;
starknet::StorageAccess::<$value_type$>::write(
address_domain,
address(key),
value,
).unwrap_syscall()
}}
}}"
)
}
Note the line
starknet::storage_base_address_from_felt252(
hash::LegacyHash::<$key_type$>::hash({address}, key))
The result of the inner hash is in the [0, PRIME)
range. However, the base address should be in the [0, 2^251 - 256)
range. Thus, there is an (incredibly small) probability of getting a panic. One solution is to take the result modulo 2^251 - 256
, as described here, although I imagine it is quite expensive.
Maybe the small probability of getting such a situation is not worth safe-guards, please tell if so and feel free to close.
Sorry, wrong Cairo