diff --git a/corelib/src/starknet/storage.cairo b/corelib/src/starknet/storage.cairo index 066d8033b9f..08b77bc4a7d 100644 --- a/corelib/src/starknet/storage.cairo +++ b/corelib/src/starknet/storage.cairo @@ -5,6 +5,9 @@ use starknet::storage_access::StorageBaseAddress; use starknet::SyscallResult; use starknet::storage_access::storage_base_address_from_felt252; +mod vec; +pub use vec::{StorageVec, StorageVecTrait, MutableStorageVecTrait}; + /// A pointer to an address in storage, can be used to read and write values, if the generic type /// supports it (e.g. basic types like `felt252`). diff --git a/corelib/src/starknet/storage/vec.cairo b/corelib/src/starknet/storage/vec.cairo new file mode 100644 index 00000000000..a7bc73bad97 --- /dev/null +++ b/corelib/src/starknet/storage/vec.cairo @@ -0,0 +1,115 @@ +use super::{ + StorageAsPath, StorageAsPointer, StoragePath, StoragePointer0Offset, Mutable, StoragePathTrait, + StoragePathUpdateTrait, StoragePointerReadAccess, StoragePointerWriteAccess +}; + +/// A type to represent a vec in storage. The length of the storage is stored in the storage +/// base, while the elements are stored in hash(storage_base, index). +#[phantom] +pub struct StorageVec {} + +impl StorageVecDrop of Drop> {} +impl StorageVecCopy of Copy> {} + +/// Implement as_ptr for StorageVec. +impl StorageVecAsPointer of StorageAsPointer>> { + type Value = u64; + fn as_ptr(self: @StoragePath>) -> StoragePointer0Offset { + StoragePointer0Offset { address: (*self).finalize() } + } +} + +/// Implement as_ptr for Mutable. +impl MutableStorageVecAsPointer of StorageAsPointer>>> { + type Value = Mutable; + fn as_ptr(self: @StoragePath>>) -> StoragePointer0Offset> { + StoragePointer0Offset { address: (*self).finalize() } + } +} + + +/// Trait for the interface of a storage vec. +pub trait StorageVecTrait { + type ElementType; + fn at(self: T, index: u64) -> StoragePath; + fn len(self: T) -> u64; +} + +/// Implement `StorageVecTrait` for `StoragePath>`. +impl StorageVecImpl of StorageVecTrait>> { + type ElementType = T; + fn at(self: StoragePath>, index: u64) -> StoragePath { + let vec_len = self.len(); + assert!(index < vec_len, "Index out of bounds"); + self.update(index) + } + fn len(self: StoragePath>) -> u64 { + self.as_ptr().read() + } +} + +/// Implement `StorageVecTrait` for any type that implements StorageAsPath into a storage path +/// that implements StorageVecTrait. +impl PathableStorageVecImpl< + T, + +Drop, + impl PathImpl: StorageAsPath, + impl VecTraitImpl: StorageVecTrait> +> of StorageVecTrait { + type ElementType = VecTraitImpl::ElementType; + fn at(self: T, index: u64) -> StoragePath { + self.as_path().at(index) + } + fn len(self: T) -> u64 { + self.as_path().len() + } +} + +/// Trait for the interface of a mutable storage vec. +pub trait MutableStorageVecTrait { + type ElementType; + fn at(self: T, index: u64) -> StoragePath>; + fn len(self: T) -> u64; + fn append(self: T) -> StoragePath>; +} + +/// Implement `MutableStorageVecTrait` for `StoragePath>`. +impl MutableStorageVecImpl< + T, +Drop +> of MutableStorageVecTrait>>> { + type ElementType = T; + fn at(self: StoragePath>>, index: u64) -> StoragePath> { + let vec_len = self.len(); + assert!(index < vec_len, "Index out of bounds"); + self.update(index) + } + fn len(self: StoragePath>>) -> u64 { + self.as_ptr().read() + } + fn append(self: StoragePath>>) -> StoragePath> { + let vec_len = self.len(); + self.as_ptr().write(vec_len + 1); + self.update(vec_len) + } +} + +/// Implement `MutableStorageVecTrait` for any type that implements StorageAsPath into a storage +/// path that implements MutableStorageVecTrait. +impl PathableMutableStorageVecImpl< + T, + +Drop, + impl PathImpl: StorageAsPath, + impl VecTraitImpl: MutableStorageVecTrait> +> of MutableStorageVecTrait { + type ElementType = VecTraitImpl::ElementType; + fn at(self: T, index: u64) -> StoragePath> { + self.as_path().at(index) + } + fn len(self: T) -> u64 { + self.as_path().len() + } + fn append(self: T) -> StoragePath> { + self.as_path().append() + } +} + diff --git a/crates/cairo-lang-starknet/cairo_level_tests/collections_test.cairo b/crates/cairo-lang-starknet/cairo_level_tests/collections_test.cairo new file mode 100644 index 00000000000..a14f4f17461 --- /dev/null +++ b/crates/cairo-lang-starknet/cairo_level_tests/collections_test.cairo @@ -0,0 +1,58 @@ +use core::starknet::storage::StoragePointerReadAccess; +use core::starknet::storage::MutableStorageVecTrait; +use core::starknet::storage::StoragePathEntry; + + +#[starknet::contract] +mod contract_with_map { + use starknet::storage::Map; + #[storage] + struct Storage { + simple: Map::, + nested: Map::>, + } +} + +#[starknet::contract] +mod contract_with_vec { + use starknet::storage::StorageVec; + #[storage] + struct Storage { + simple: StorageVec::, + nested: StorageVec::>, + } +} + +#[test] +fn test_simple_member_write_to_map() { + let mut map_contract_state = contract_with_map::contract_state_for_testing(); + let mut vec_contract_state = contract_with_vec::contract_state_for_testing(); + let vec_entry = vec_contract_state.simple.append(); + map_contract_state.simple.entry(0).write(1); + assert_eq!(vec_entry.read(), 1); +} + +#[test] +fn test_simple_member_write_to_vec() { + let mut map_contract_state = contract_with_map::contract_state_for_testing(); + let mut vec_contract_state = contract_with_vec::contract_state_for_testing(); + vec_contract_state.simple.append().write(1); + assert_eq!(map_contract_state.simple.entry(0).read(), 1); +} + +#[test] +fn test_nested_member_write_to_map() { + let mut map_contract_state = contract_with_map::contract_state_for_testing(); + let mut vec_contract_state = contract_with_vec::contract_state_for_testing(); + let vec_entry = vec_contract_state.nested.append().append(); + map_contract_state.nested.entry(0).entry(0).write(1); + assert_eq!(vec_entry.read(), 1); +} + +#[test] +fn test_nested_member_write_to_vec() { + let mut map_contract_state = contract_with_map::contract_state_for_testing(); + let mut vec_contract_state = contract_with_vec::contract_state_for_testing(); + vec_contract_state.nested.append().append().write(1); + assert_eq!(map_contract_state.nested.entry(0).entry(0).read(), 1); +} diff --git a/crates/cairo-lang-starknet/cairo_level_tests/lib.cairo b/crates/cairo-lang-starknet/cairo_level_tests/lib.cairo index 605becf8911..1e2b6518767 100644 --- a/crates/cairo-lang-starknet/cairo_level_tests/lib.cairo +++ b/crates/cairo-lang-starknet/cairo_level_tests/lib.cairo @@ -25,3 +25,5 @@ mod storage_access; #[cfg(test)] mod contract_address_test; mod utils; +#[cfg(test)] +mod collections_test; \ No newline at end of file diff --git a/crates/cairo-lang-starknet/cairo_level_tests/storage_access.cairo b/crates/cairo-lang-starknet/cairo_level_tests/storage_access.cairo index 55b892d0988..19a0ce032c6 100644 --- a/crates/cairo-lang-starknet/cairo_level_tests/storage_access.cairo +++ b/crates/cairo-lang-starknet/cairo_level_tests/storage_access.cairo @@ -4,6 +4,7 @@ use super::utils::{deserialized, serialized}; use core::integer::BoundedInt; use core::num::traits::Zero; use core::byte_array::ByteArrayTrait; +use starknet::storage::StorageVec; impl StorageAddressPartialEq of PartialEq { fn eq(lhs: @StorageAddress, rhs: @StorageAddress) -> bool { @@ -78,15 +79,24 @@ struct NonZeros { value_felt252: NonZero, } +#[starknet::storage_node] +struct StorageVecs { + vec: StorageVec, + vec_of_vecs: StorageVec>, +} + #[starknet::contract] mod test_contract { - use super::{AbcEtc, ByteArrays, NonZeros}; + use core::starknet::storage::StoragePointerWriteAccess; + use super::{AbcEtc, ByteArrays, NonZeros, StorageVecs,}; + use starknet::storage::{StorageVecTrait, MutableStorageVecTrait, StorageAsPath,}; #[storage] struct Storage { data: AbcEtc, byte_arrays: ByteArrays, non_zeros: NonZeros, + vecs: StorageVecs, } #[external(v0)] @@ -128,6 +138,46 @@ mod test_contract { pub fn get_non_zeros(self: @ContractState) -> NonZeros { self.non_zeros.read() } + + #[external(v0)] + pub fn append_to_vec(ref self: ContractState, value: u32) { + self.vecs.vec.append().write(value); + } + + #[external(v0)] + pub fn get_vec_length(self: @ContractState) -> u64 { + self.vecs.vec.len() + } + + #[external(v0)] + pub fn get_vec_element(self: @ContractState, index: u64) -> u32 { + self.vecs.vec.at(index).read() + } + + #[external(v0)] + pub fn append_an_vec(ref self: ContractState) { + self.vecs.vec_of_vecs.append(); + } + + #[external(v0)] + pub fn append_to_nested_vec(ref self: ContractState, index: u64, value: u32) { + self.vecs.vec_of_vecs.at(index).append().write(value); + } + + #[external(v0)] + pub fn get_vec_of_vecs_length(self: @ContractState) -> u64 { + self.vecs.vec_of_vecs.len() + } + + #[external(v0)] + pub fn get_nested_vec_length(self: @ContractState, index: u64) -> u64 { + self.vecs.vec_of_vecs.at(index).len() + } + + #[external(v0)] + pub fn get_nested_vec_element(self: @ContractState, index: u64, nested_index: u64) -> u32 { + self.vecs.vec_of_vecs.at(index).at(nested_index).read() + } } #[test] @@ -224,3 +274,52 @@ fn test_read_write_non_zero() { assert!(test_contract::__external::set_non_zeros(serialized(x.clone())).is_empty()); assert_eq!(deserialized(test_contract::__external::get_non_zeros(serialized(()))), x); } + +#[test] +fn test_storage_array() { + assert!(test_contract::__external::append_to_vec(serialized(1_u32)).is_empty()); + assert!(test_contract::__external::append_to_vec(serialized(2_u32)).is_empty()); + assert!(test_contract::__external::append_to_vec(serialized(3_u32)).is_empty()); + assert_eq!(deserialized(test_contract::__external::get_vec_length(serialized(()))), 3); + assert_eq!(deserialized(test_contract::__external::get_vec_element(serialized(0_u64))), 1); + assert_eq!(deserialized(test_contract::__external::get_vec_element(serialized(1_u64))), 2); + assert_eq!(deserialized(test_contract::__external::get_vec_element(serialized(2_u64))), 3); +} + +#[test] +fn test_storage_vec_of_vecs() { + assert!(test_contract::__external::append_an_vec(serialized(())).is_empty()); + assert!(test_contract::__external::append_to_nested_vec(serialized((0_u64, 1_u32))).is_empty()); + assert!(test_contract::__external::append_to_nested_vec(serialized((0_u64, 2_u32))).is_empty()); + assert!(test_contract::__external::append_to_nested_vec(serialized((0_u64, 3_u32))).is_empty()); + assert!(test_contract::__external::append_an_vec(serialized(())).is_empty()); + assert!(test_contract::__external::append_to_nested_vec(serialized((1_u64, 4_u32))).is_empty()); + assert!(test_contract::__external::append_to_nested_vec(serialized((1_u64, 5_u32))).is_empty()); + assert_eq!(deserialized(test_contract::__external::get_vec_of_vecs_length(serialized(()))), 2); + assert_eq!( + deserialized(test_contract::__external::get_nested_vec_length(serialized(0_u64))), 3 + ); + assert_eq!( + deserialized(test_contract::__external::get_nested_vec_element(serialized((0_u64, 0_u64)))), + 1 + ); + assert_eq!( + deserialized(test_contract::__external::get_nested_vec_element(serialized((0_u64, 1_u64)))), + 2 + ); + assert_eq!( + deserialized(test_contract::__external::get_nested_vec_element(serialized((0_u64, 2_u64)))), + 3 + ); + assert_eq!( + deserialized(test_contract::__external::get_nested_vec_length(serialized(1_u64))), 2 + ); + assert_eq!( + deserialized(test_contract::__external::get_nested_vec_element(serialized((1_u64, 0_u64)))), + 4 + ); + assert_eq!( + deserialized(test_contract::__external::get_nested_vec_element(serialized((1_u64, 1_u64)))), + 5 + ); +} diff --git a/crates/cairo-lang-starknet/src/plugin/plugin_test_data/contracts/new_storage_interface b/crates/cairo-lang-starknet/src/plugin/plugin_test_data/contracts/new_storage_interface index c302ef28cf1..d6745454723 100644 --- a/crates/cairo-lang-starknet/src/plugin/plugin_test_data/contracts/new_storage_interface +++ b/crates/cairo-lang-starknet/src/plugin/plugin_test_data/contracts/new_storage_interface @@ -25,6 +25,8 @@ trait HelloStarknetTrait { fn get_balance_trio_sub_member(self: @TContractState) -> u128; fn set_balance_trio_sub_member(ref self: TContractState, value: u128); fn get_third_list_value(self: @TContractState) -> felt252; + fn get_arr_at(self: @TContractState, index: u64) -> usize; + fn append_to_arr(ref self: TContractState, value: usize); } #[starknet::storage_node] @@ -54,7 +56,8 @@ struct LinkedList { #[starknet::contract] mod hello_starknet { use starknet::storage::{ - StorageAsPointer, StorageAsPath, StoragePathEntry, Map, SubPointersDeref + StorageAsPointer, StorageAsPath, StoragePathEntry, Map, SubPointersDeref, StorageVec, + StorageVecTrait, MutableStorageVecTrait }; use super::{BalancePair, SlicedBalancePair, SlicedBalanceTrio, LinkedList}; use super::MutableBalancePairStorageNodeImpl; @@ -67,6 +70,7 @@ mod hello_starknet { balance_pair: BalancePair, sliced_balance_trio: SlicedBalanceTrio, linked_list: LinkedList, + arr: StorageVec, } #[abi(embed_v0)] @@ -114,6 +118,12 @@ mod hello_starknet { fn get_third_list_value(self: @ContractState) -> felt252 { self.linked_list.next.next.value.read() } + fn get_arr_at(self: @ContractState, index: u64) -> usize { + self.arr.at(index).read() + } + fn append_to_arr(ref self: ContractState, value: usize) { + self.arr.append().write(value); + } } } @@ -141,6 +151,8 @@ trait HelloStarknetTrait { fn get_balance_trio_sub_member(self: @TContractState) -> u128; fn set_balance_trio_sub_member(ref self: TContractState, value: u128); fn get_third_list_value(self: @TContractState) -> felt252; + fn get_arr_at(self: @TContractState, index: u64) -> usize; + fn append_to_arr(ref self: TContractState, value: usize); } #[starknet::storage_node] @@ -170,7 +182,8 @@ struct LinkedList { #[starknet::contract] mod hello_starknet { use starknet::storage::{ - StorageAsPointer, StorageAsPath, StoragePathEntry, Map, SubPointersDeref + StorageAsPointer, StorageAsPath, StoragePathEntry, Map, SubPointersDeref, StorageVec, + StorageVecTrait, MutableStorageVecTrait }; use super::{BalancePair, SlicedBalancePair, SlicedBalanceTrio, LinkedList}; use super::MutableBalancePairStorageNodeImpl; @@ -183,6 +196,7 @@ mod hello_starknet { balance_pair: BalancePair, sliced_balance_trio: SlicedBalanceTrio, linked_list: LinkedList, + arr: StorageVec, } #[abi(embed_v0)] @@ -230,6 +244,12 @@ mod hello_starknet { fn get_third_list_value(self: @ContractState) -> felt252 { self.linked_list.next.next.value.read() } + fn get_arr_at(self: @ContractState, index: u64) -> usize { + self.arr.at(index).read() + } + fn append_to_arr(ref self: ContractState, value: usize) { + self.arr.append().write(value); + } } } @@ -258,6 +278,8 @@ self: T, user_id: usize, subbalance_id: usize fn get_balance_trio_sub_member(self: T) -> u128; fn set_balance_trio_sub_member(self: T, value: u128); fn get_third_list_value(self: T) -> felt252; + fn get_arr_at(self: T, index: u64) -> usize; + fn append_to_arr(self: T, value: usize); } #[derive(Copy, Drop, starknet::Store, Serde)] @@ -451,6 +473,33 @@ self: HelloStarknetTraitDispatcher, user_id: usize, subbalance_id: usize 'Returned data too short', ) } + fn get_arr_at(self: HelloStarknetTraitDispatcher, index: u64) -> usize { + let mut __calldata__ = core::traits::Default::default(); + core::serde::Serde::::serialize(@index, ref __calldata__); + + let mut __dispatcher_return_data__ = starknet::syscalls::call_contract_syscall( + self.contract_address, + selector!("get_arr_at"), + core::array::ArrayTrait::span(@__calldata__), + ); + let mut __dispatcher_return_data__ = starknet::SyscallResultTrait::unwrap_syscall(__dispatcher_return_data__); + core::option::OptionTrait::expect( + core::serde::Serde::::deserialize(ref __dispatcher_return_data__), + 'Returned data too short', + ) + } + fn append_to_arr(self: HelloStarknetTraitDispatcher, value: usize) { + let mut __calldata__ = core::traits::Default::default(); + core::serde::Serde::::serialize(@value, ref __calldata__); + + let mut __dispatcher_return_data__ = starknet::syscalls::call_contract_syscall( + self.contract_address, + selector!("append_to_arr"), + core::array::ArrayTrait::span(@__calldata__), + ); + let mut __dispatcher_return_data__ = starknet::SyscallResultTrait::unwrap_syscall(__dispatcher_return_data__); + () + } } @@ -645,6 +694,33 @@ self: HelloStarknetTraitLibraryDispatcher, user_id: usize, subbalance_id: usize 'Returned data too short', ) } + fn get_arr_at(self: HelloStarknetTraitLibraryDispatcher, index: u64) -> usize { + let mut __calldata__ = core::traits::Default::default(); + core::serde::Serde::::serialize(@index, ref __calldata__); + + let mut __dispatcher_return_data__ = starknet::syscalls::library_call_syscall( + self.class_hash, + selector!("get_arr_at"), + core::array::ArrayTrait::span(@__calldata__), + ); + let mut __dispatcher_return_data__ = starknet::SyscallResultTrait::unwrap_syscall(__dispatcher_return_data__); + core::option::OptionTrait::expect( + core::serde::Serde::::deserialize(ref __dispatcher_return_data__), + 'Returned data too short', + ) + } + fn append_to_arr(self: HelloStarknetTraitLibraryDispatcher, value: usize) { + let mut __calldata__ = core::traits::Default::default(); + core::serde::Serde::::serialize(@value, ref __calldata__); + + let mut __dispatcher_return_data__ = starknet::syscalls::library_call_syscall( + self.class_hash, + selector!("append_to_arr"), + core::array::ArrayTrait::span(@__calldata__), + ); + let mut __dispatcher_return_data__ = starknet::SyscallResultTrait::unwrap_syscall(__dispatcher_return_data__); + () + } } @@ -681,6 +757,10 @@ self: T, user_id: usize, subbalance_id: usize fn set_balance_trio_sub_member(self: T, value: u128) -> starknet::SyscallResult<()>; #[unstable(feature: "safe_dispatcher")] fn get_third_list_value(self: T) -> starknet::SyscallResult; + #[unstable(feature: "safe_dispatcher")] + fn get_arr_at(self: T, index: u64) -> starknet::SyscallResult; + #[unstable(feature: "safe_dispatcher")] + fn append_to_arr(self: T, value: usize) -> starknet::SyscallResult<()>; } #[derive(Copy, Drop, starknet::Store, Serde)] @@ -890,6 +970,35 @@ self: HelloStarknetTraitSafeLibraryDispatcher, user_id: usize, subbalance_id: us ) ) } + fn get_arr_at(self: HelloStarknetTraitSafeLibraryDispatcher, index: u64) -> starknet::SyscallResult { + let mut __calldata__ = core::traits::Default::default(); + core::serde::Serde::::serialize(@index, ref __calldata__); + + let mut __dispatcher_return_data__ = starknet::syscalls::library_call_syscall( + self.class_hash, + selector!("get_arr_at"), + core::array::ArrayTrait::span(@__calldata__), + ); + let mut __dispatcher_return_data__ = __dispatcher_return_data__?; + Result::Ok( + core::option::OptionTrait::expect( + core::serde::Serde::::deserialize(ref __dispatcher_return_data__), + 'Returned data too short', + ) + ) + } + fn append_to_arr(self: HelloStarknetTraitSafeLibraryDispatcher, value: usize) -> starknet::SyscallResult<()> { + let mut __calldata__ = core::traits::Default::default(); + core::serde::Serde::::serialize(@value, ref __calldata__); + + let mut __dispatcher_return_data__ = starknet::syscalls::library_call_syscall( + self.class_hash, + selector!("append_to_arr"), + core::array::ArrayTrait::span(@__calldata__), + ); + let mut __dispatcher_return_data__ = __dispatcher_return_data__?; + Result::Ok(()) + } } @@ -1101,11 +1210,40 @@ self: HelloStarknetTraitSafeDispatcher, user_id: usize, subbalance_id: usize ) ) } + fn get_arr_at(self: HelloStarknetTraitSafeDispatcher, index: u64) -> starknet::SyscallResult { + let mut __calldata__ = core::traits::Default::default(); + core::serde::Serde::::serialize(@index, ref __calldata__); + + let mut __dispatcher_return_data__ = starknet::syscalls::call_contract_syscall( + self.contract_address, + selector!("get_arr_at"), + core::array::ArrayTrait::span(@__calldata__), + ); + let mut __dispatcher_return_data__ = __dispatcher_return_data__?; + Result::Ok( + core::option::OptionTrait::expect( + core::serde::Serde::::deserialize(ref __dispatcher_return_data__), + 'Returned data too short', + ) + ) + } + fn append_to_arr(self: HelloStarknetTraitSafeDispatcher, value: usize) -> starknet::SyscallResult<()> { + let mut __calldata__ = core::traits::Default::default(); + core::serde::Serde::::serialize(@value, ref __calldata__); + + let mut __dispatcher_return_data__ = starknet::syscalls::call_contract_syscall( + self.contract_address, + selector!("append_to_arr"), + core::array::ArrayTrait::span(@__calldata__), + ); + let mut __dispatcher_return_data__ = __dispatcher_return_data__?; + Result::Ok(()) + } } -lib.cairo:24:1 +lib.cairo:26:1 #[starknet::storage_node] ^***********************^ storage_node: @@ -1158,7 +1296,7 @@ type NodeType = MutableBalancePairStorageNode; } -lib.cairo:29:1 +lib.cairo:31:1 ^ impls: @@ -1166,7 +1304,7 @@ impls: impl SlicedBalanceTrioDrop of core::traits::Drop::; -lib.cairo:30:16 +lib.cairo:32:16 #[derive(Drop, starknet::Store)] ^*************^ starknet_derive: @@ -1266,7 +1404,7 @@ type SubPointersType = MutableSlicedBalanceTrioSubPointers; } -lib.cairo:35:1 +lib.cairo:37:1 ^ impls: @@ -1274,7 +1412,7 @@ impls: impl SlicedBalancePairDrop of core::traits::Drop::; -lib.cairo:36:16 +lib.cairo:38:16 #[derive(Drop, starknet::Store)] ^*************^ starknet_derive: @@ -1374,7 +1512,7 @@ type SubPointersType = MutableSlicedBalancePairSubPointers; } -lib.cairo:42:1 +lib.cairo:44:1 #[starknet::storage_node] ^***********************^ storage_node: @@ -1803,7 +1941,7 @@ type SubPointersType = MutableHelloStarknetTraitSafeDispatcherSubPointers; } -lib.cairo:24:1 +lib.cairo:26:1 #[starknet::storage_node] ^***********************^ impls: @@ -1812,7 +1950,7 @@ impl BalancePairStorageNodeDrop of core::traits::Drop::; impl BalancePairStorageNodeCopy of core::traits::Copy::; -lib.cairo:24:1 +lib.cairo:26:1 #[starknet::storage_node] ^***********************^ impls: @@ -1821,7 +1959,7 @@ impl MutableBalancePairStorageNodeDrop of core::traits::Drop::; -lib.cairo:30:16 +lib.cairo:32:16 #[derive(Drop, starknet::Store)] ^*************^ impls: @@ -1830,7 +1968,7 @@ impl SlicedBalanceTrioSubPointersDrop of core::traits::Drop::; -lib.cairo:30:16 +lib.cairo:32:16 #[derive(Drop, starknet::Store)] ^*************^ impls: @@ -1839,7 +1977,7 @@ impl MutableSlicedBalanceTrioSubPointersDrop of core::traits::Drop::; -lib.cairo:36:16 +lib.cairo:38:16 #[derive(Drop, starknet::Store)] ^*************^ impls: @@ -1848,7 +1986,7 @@ impl SlicedBalancePairSubPointersDrop of core::traits::Drop::; -lib.cairo:36:16 +lib.cairo:38:16 #[derive(Drop, starknet::Store)] ^*************^ impls: @@ -1857,7 +1995,7 @@ impl MutableSlicedBalancePairSubPointersDrop of core::traits::Drop::; -lib.cairo:42:1 +lib.cairo:44:1 #[starknet::storage_node] ^***********************^ impls: @@ -1866,7 +2004,7 @@ impl LinkedListStorageNodeDrop of core::traits::Drop::; impl LinkedListStorageNodeCopy of core::traits::Copy::; -lib.cairo:42:1 +lib.cairo:44:1 #[starknet::storage_node] ^***********************^ impls: @@ -1947,7 +2085,7 @@ impl MutableHelloStarknetTraitSafeDispatcherSubPointersDrop of core::traits::Dro impl MutableHelloStarknetTraitSafeDispatcherSubPointersCopy of core::traits::Copy::; -lib.cairo:48:1 +lib.cairo:50:1 #[starknet::contract] ^*******************^ contract: @@ -1966,6 +2104,7 @@ pub struct Storage { pub balance_pair: BalancePair, pub sliced_balance_trio: SlicedBalanceTrio, pub linked_list: LinkedList, + pub arr: StorageVec, } #[derive(Drop, Copy)] @@ -1977,6 +2116,7 @@ pub struct ContractStorageBase { pub balance_pair: starknet::storage::StorageBase, pub sliced_balance_trio: starknet::storage::StorageBase, pub linked_list: starknet::storage::StorageBase, + pub arr: starknet::storage::StorageBase>, } #[derive(Drop, Copy)] pub struct ContractStorageBaseMut { @@ -1987,6 +2127,7 @@ pub struct ContractStorageBaseMut { pub balance_pair: starknet::storage::StorageBase>, pub sliced_balance_trio: starknet::storage::StorageBase>, pub linked_list: starknet::storage::StorageBase>, + pub arr: starknet::storage::StorageBase>>, } impl StorageBaseImpl of starknet::storage::StorageBaseTrait { type BaseType = ContractStorageBase; @@ -2000,6 +2141,7 @@ impl StorageBaseImpl of starknet::storage::StorageBaseTrait { balance_pair: starknet::storage::StorageBase{ address: selector!("balance_pair") }, sliced_balance_trio: starknet::storage::StorageBase{ address: selector!("sliced_balance_trio") }, linked_list: starknet::storage::StorageBase{ address: selector!("linked_list") }, + arr: starknet::storage::StorageBase{ address: selector!("arr") }, } } fn storage_base_mut(ref self: ContractState) -> ContractStorageBaseMut { @@ -2011,6 +2153,7 @@ impl StorageBaseImpl of starknet::storage::StorageBaseTrait { balance_pair: starknet::storage::StorageBase{ address: selector!("balance_pair") }, sliced_balance_trio: starknet::storage::StorageBase{ address: selector!("sliced_balance_trio") }, linked_list: starknet::storage::StorageBase{ address: selector!("linked_list") }, + arr: starknet::storage::StorageBase{ address: selector!("arr") }, } } } @@ -2048,7 +2191,7 @@ pub fn contract_state_for_testing() -> ContractState { )] use starknet::storage::Map as LegacyMap; #[cfg(target: 'test')] -pub const TEST_CLASS_HASH: felt252 = 0x29e7f88fe33b0c80d1d63769fd10e46da6bc5e3f7261a1c10d02af304d6d4d5; +pub const TEST_CLASS_HASH: felt252 = 0x2c32c785ccb6dc205e673c44f7b9939345d157be6ee46b0f5753bf758c0b857; #[implicit_precedence(Pedersen, RangeCheck, Bitwise, core::ec::EcOp, Poseidon, SegmentArena, core::circuit::RangeCheck96, core::circuit::AddMod, core::circuit::MulMod, GasBuiltin, System)] fn __wrapper__HelloStarknetImpl__increase_balance(mut data: Span::) -> Span:: { @@ -2328,6 +2471,49 @@ fn __wrapper__HelloStarknetImpl__get_third_list_value(mut data: Span::) core::array::ArrayTrait::span(@arr) } +#[implicit_precedence(Pedersen, RangeCheck, Bitwise, core::ec::EcOp, Poseidon, SegmentArena, core::circuit::RangeCheck96, core::circuit::AddMod, core::circuit::MulMod, GasBuiltin, System)] +fn __wrapper__HelloStarknetImpl__get_arr_at(mut data: Span::) -> Span:: { + core::internal::require_implicit::(); + core::internal::revoke_ap_tracking(); + core::option::OptionTraitImpl::expect(core::gas::withdraw_gas(), 'Out of gas'); + let __arg_index = core::option::OptionTraitImpl::expect( + core::serde::Serde::::deserialize(ref data), + 'Failed to deserialize param #1' + ); + assert(core::array::SpanTrait::is_empty(data), 'Input too long for arguments'); + core::option::OptionTraitImpl::expect( + core::gas::withdraw_gas_all(core::gas::get_builtin_costs()), 'Out of gas', + ); + let mut contract_state = unsafe_new_contract_state(); + let res = HelloStarknetImpl::get_arr_at(@contract_state, __arg_index); + let mut arr = ArrayTrait::new(); + // References. + // Result. + core::serde::Serde::::serialize(@res, ref arr); + core::array::ArrayTrait::span(@arr) +} + +#[implicit_precedence(Pedersen, RangeCheck, Bitwise, core::ec::EcOp, Poseidon, SegmentArena, core::circuit::RangeCheck96, core::circuit::AddMod, core::circuit::MulMod, GasBuiltin, System)] +fn __wrapper__HelloStarknetImpl__append_to_arr(mut data: Span::) -> Span:: { + core::internal::require_implicit::(); + core::internal::revoke_ap_tracking(); + core::option::OptionTraitImpl::expect(core::gas::withdraw_gas(), 'Out of gas'); + let __arg_value = core::option::OptionTraitImpl::expect( + core::serde::Serde::::deserialize(ref data), + 'Failed to deserialize param #1' + ); + assert(core::array::SpanTrait::is_empty(data), 'Input too long for arguments'); + core::option::OptionTraitImpl::expect( + core::gas::withdraw_gas_all(core::gas::get_builtin_costs()), 'Out of gas', + ); + let mut contract_state = unsafe_new_contract_state(); + HelloStarknetImpl::append_to_arr(ref contract_state, __arg_value); + let mut arr = ArrayTrait::new(); + // References. + // Result. + core::array::ArrayTrait::span(@arr) +} + pub mod __external { pub use super::__wrapper__HelloStarknetImpl__increase_balance as increase_balance; @@ -2343,6 +2529,8 @@ pub mod __external { pub use super::__wrapper__HelloStarknetImpl__get_balance_trio_sub_member as get_balance_trio_sub_member; pub use super::__wrapper__HelloStarknetImpl__set_balance_trio_sub_member as set_balance_trio_sub_member; pub use super::__wrapper__HelloStarknetImpl__get_third_list_value as get_third_list_value; + pub use super::__wrapper__HelloStarknetImpl__get_arr_at as get_arr_at; + pub use super::__wrapper__HelloStarknetImpl__append_to_arr as append_to_arr; } pub mod __l1_handler { } @@ -2369,7 +2557,7 @@ pub mod __constructor { -lib.cairo:48:1 +lib.cairo:50:1 #[starknet::contract] ^*******************^ impls: @@ -2377,7 +2565,7 @@ impls: impl EventDrop of core::traits::Drop::; -lib.cairo:48:1 +lib.cairo:50:1 #[starknet::contract] ^*******************^ starknet_derive: @@ -2399,7 +2587,7 @@ impl EventIsEvent of starknet::Event { -lib.cairo:48:1 +lib.cairo:50:1 #[starknet::contract] ^*******************^ impls: @@ -2408,7 +2596,7 @@ impl ContractStorageBaseDrop of core::traits::Drop::; impl ContractStorageBaseCopy of core::traits::Copy::; -lib.cairo:48:1 +lib.cairo:50:1 #[starknet::contract] ^*******************^ impls: @@ -2418,16 +2606,16 @@ impl ContractStorageBaseMutCopy of core::traits::Copy::; //! > expected_diagnostics warning: Usage of deprecated feature `"deprecated_legacy_map"` with no `#[feature("deprecated_legacy_map")]` attribute. Note: "Use `starknet::storage::Map` instead." - --> lib.cairo:60:28 + --> lib.cairo:63:28 legacy_map_balace: LegacyMap, ^*******^ warning: Usage of deprecated feature `"deprecated_legacy_map"` with no `#[feature("deprecated_legacy_map")]` attribute. Note: "Use `starknet::storage::Map` instead." - --> lib.cairo:60:28 + --> lib.cairo:63:28 legacy_map_balace: LegacyMap, ^*******^ warning: Usage of deprecated feature `"deprecated_legacy_map"` with no `#[feature("deprecated_legacy_map")]` attribute. Note: "Use `starknet::storage::Map` instead." - --> lib.cairo:60:28 + --> lib.cairo:63:28 legacy_map_balace: LegacyMap, ^*******^