@@ -46,14 +46,6 @@ type CallOf<T> = <T as frame_system::Config>::RuntimeCall;
46
46
/// The maximum nesting depth a contract can use when encoding types.
47
47
const MAX_DECODE_NESTING : u32 = 256 ;
48
48
49
- enum StorageValue {
50
- Memory { ptr : u32 , len : u32 } ,
51
- Value ( Vec < u8 > ) ,
52
- }
53
- enum StorageReadMode {
54
- ErrorIfMissing ,
55
- ZeroIfMissing ,
56
- }
57
49
/// Abstraction over the memory access within syscalls.
58
50
///
59
51
/// The reason for this abstraction is that we run syscalls on the host machine when
@@ -614,6 +606,23 @@ fn extract_hi_lo(reg: u64) -> (u32, u32) {
614
606
( ( reg >> 32 ) as u32 , reg as u32 )
615
607
}
616
608
609
+ /// Represents different forms of storage values for operations.
610
+ enum StorageValue {
611
+ /// Used for variable-length values in traditional storage functions.
612
+ Memory { ptr : u32 , len : u32 } ,
613
+ /// Used to implement Ethereum SSTORE-like semantics for fixed-size (256-bit) key and values.
614
+ Value ( Vec < u8 > ) ,
615
+ }
616
+
617
+ /// Determines behavior when a key doesn't exist during storage read operations.
618
+ enum StorageReadMode {
619
+ /// Return KeyNotFound error code when the key doesn't exist.
620
+ /// Used in traditional variable-length storage functions.
621
+ ErrorIfMissing ,
622
+ /// Write zeros to the output buffer when the key doesn't exist.
623
+ /// Used to implement Ethereum SLOAD-like semantics for fixed-size (256-bit) key and output.
624
+ ZeroIfMissing ,
625
+ }
617
626
/// Can only be used for one call.
618
627
pub struct Runtime < ' a , E : Ext , M : ?Sized > {
619
628
ext : & ' a mut E ,
@@ -891,9 +900,9 @@ impl<'a, E: Ext, M: ?Sized + Memory<E::T>> Runtime<'a, E, M> {
891
900
}
892
901
} ;
893
902
894
- let ( value_len, _ ) = match & value {
895
- StorageValue :: Memory { ptr : _, len } => ( * len, None ) ,
896
- StorageValue :: Value ( data) => ( data. len ( ) as u32 , Some ( data . clone ( ) ) ) ,
903
+ let value_len = match & value {
904
+ StorageValue :: Memory { ptr : _, len } => * len,
905
+ StorageValue :: Value ( data) => data. len ( ) as u32 ,
897
906
} ;
898
907
899
908
let max_size = self . ext . max_value_size ( ) ;
@@ -904,15 +913,15 @@ impl<'a, E: Ext, M: ?Sized + Memory<E::T>> Runtime<'a, E, M> {
904
913
905
914
let key = self . decode_key ( memory, key_ptr, key_len) ?;
906
915
907
- let value_data = match value {
916
+ let value = match value {
908
917
StorageValue :: Memory { ptr, len } => Some ( memory. read ( ptr, len) ?) ,
909
918
StorageValue :: Value ( data) => Some ( data) ,
910
919
} ;
911
920
912
921
let write_outcome = if transient {
913
- self . ext . set_transient_storage ( & key, value_data , false ) ?
922
+ self . ext . set_transient_storage ( & key, value , false ) ?
914
923
} else {
915
- self . ext . set_storage ( & key, value_data , false ) ?
924
+ self . ext . set_storage ( & key, value , false ) ?
916
925
} ;
917
926
918
927
self . adjust_gas ( charged, costs ( value_len, write_outcome. old_len ( ) ) ) ;
@@ -977,7 +986,7 @@ impl<'a, E: Ext, M: ?Sized + Memory<E::T>> Runtime<'a, E, M> {
977
986
// For fixed-size operations use write_fixed_sandbox_output
978
987
if out_len_ptr == SENTINEL {
979
988
let mut fixed_output = [ 0u8 ; 32 ] ;
980
- let len = std :: cmp:: min ( value. len ( ) , 32 ) ;
989
+ let len = core :: cmp:: min ( value. len ( ) , 32 ) ;
981
990
fixed_output[ ..len] . copy_from_slice ( & value[ ..len] ) ;
982
991
983
992
self . write_fixed_sandbox_output (
@@ -1289,6 +1298,27 @@ pub mod env {
1289
1298
)
1290
1299
}
1291
1300
1301
+ /// Sets the storage at a fixed 256-bit key with a fixed 256-bit value.
1302
+ /// See [`pallet_revive_uapi::HostFn::set_storage_or_clear`].
1303
+ #[ stable]
1304
+ #[ mutating]
1305
+ fn set_storage_or_clear (
1306
+ & mut self ,
1307
+ memory : & mut M ,
1308
+ flags : u32 ,
1309
+ key_ptr : u32 ,
1310
+ value_ptr : u32 ,
1311
+ ) -> Result < u32 , TrapReason > {
1312
+ let _ = Self :: is_transient ( flags) ?;
1313
+ let value = memory. read_array :: < 32 > ( value_ptr) ?;
1314
+
1315
+ if value. iter ( ) . all ( |& b| b == 0 ) {
1316
+ self . clear_storage ( memory, flags, key_ptr, SENTINEL )
1317
+ } else {
1318
+ self . set_storage ( memory, flags, key_ptr, SENTINEL , StorageValue :: Value ( value. to_vec ( ) ) )
1319
+ }
1320
+ }
1321
+
1292
1322
/// Retrieve the value under the given key from storage.
1293
1323
/// See [`pallet_revive_uapi::HostFn::get_storage`]
1294
1324
#[ stable]
@@ -1312,6 +1342,29 @@ pub mod env {
1312
1342
)
1313
1343
}
1314
1344
1345
+ /// Reads the storage at a fixed 256-bit key and writes back a fixed 256-bit value.
1346
+ /// See [`pallet_revive_uapi::HostFn::get_storage_or_zero`].
1347
+ #[ stable]
1348
+ fn get_storage_or_zero (
1349
+ & mut self ,
1350
+ memory : & mut M ,
1351
+ flags : u32 ,
1352
+ key_ptr : u32 ,
1353
+ out_ptr : u32 ,
1354
+ ) -> Result < ( ) , TrapReason > {
1355
+ let _ = self . get_storage (
1356
+ memory,
1357
+ flags,
1358
+ key_ptr,
1359
+ SENTINEL ,
1360
+ out_ptr,
1361
+ SENTINEL ,
1362
+ StorageReadMode :: ZeroIfMissing ,
1363
+ ) ?;
1364
+
1365
+ Ok ( ( ) )
1366
+ }
1367
+
1315
1368
/// Make a call to another contract.
1316
1369
/// See [`pallet_revive_uapi::HostFn::call`].
1317
1370
#[ stable]
@@ -1888,50 +1941,6 @@ pub mod env {
1888
1941
Ok ( self . ext . gas_meter ( ) . gas_left ( ) . ref_time ( ) )
1889
1942
}
1890
1943
1891
- /// Sets the storage at a fixed 256-bit key with a fixed 256-bit value.
1892
- /// See [`pallet_revive_uapi::HostFn::set_storage_or_clear`].
1893
- #[ stable]
1894
- #[ mutating]
1895
- fn set_storage_or_clear (
1896
- & mut self ,
1897
- memory : & mut M ,
1898
- flags : u32 ,
1899
- key_ptr : u32 ,
1900
- value_ptr : u32 ,
1901
- ) -> Result < u32 , TrapReason > {
1902
- let _ = Self :: is_transient ( flags) ?;
1903
- let value = memory. read_array :: < 32 > ( value_ptr) ?;
1904
-
1905
- if value. iter ( ) . all ( |& b| b == 0 ) {
1906
- self . clear_storage ( memory, flags, key_ptr, SENTINEL )
1907
- } else {
1908
- self . set_storage ( memory, flags, key_ptr, SENTINEL , StorageValue :: Value ( value. to_vec ( ) ) )
1909
- }
1910
- }
1911
-
1912
- /// Reads the storage at a fixed 256-bit key and writes back a fixed 256-bit value.
1913
- /// See [`pallet_revive_uapi::HostFn::get_storage_or_zero`].
1914
- #[ stable]
1915
- fn get_storage_or_zero (
1916
- & mut self ,
1917
- memory : & mut M ,
1918
- flags : u32 ,
1919
- key_ptr : u32 ,
1920
- out_ptr : u32 ,
1921
- ) -> Result < ( ) , TrapReason > {
1922
- let _ = self . get_storage (
1923
- memory,
1924
- flags,
1925
- key_ptr,
1926
- SENTINEL ,
1927
- out_ptr,
1928
- SENTINEL ,
1929
- StorageReadMode :: ZeroIfMissing ,
1930
- ) ?;
1931
-
1932
- Ok ( ( ) )
1933
- }
1934
-
1935
1944
/// Call into the chain extension provided by the chain if any.
1936
1945
/// See [`pallet_revive_uapi::HostFn::call_chain_extension`].
1937
1946
fn call_chain_extension (
0 commit comments