Skip to content

Commit be2d6ae

Browse files
authored
Do not read from state when writing aligned, slot sized values (#7470)
1 parent d6b9a87 commit be2d6ae

File tree

9 files changed

+91
-7
lines changed

9 files changed

+91
-7
lines changed

forc-plugins/forc-client/tests/deploy.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ async fn test_simple_deploy() {
377377
node.kill().unwrap();
378378
let expected = vec![DeployedPackage::Contract(DeployedContract {
379379
id: ContractId::from_str(
380-
"91c435d6cdb720db92097958163bc43dbc5c4acfbb3d98025039addb9e2da8bb",
380+
"b9443b8e389d42e551b80bb7e94adb4dd37c6985088401940035e36489c90af8",
381381
)
382382
.unwrap(),
383383
proxy: None,
@@ -421,7 +421,7 @@ async fn test_deploy_submit_only() {
421421
node.kill().unwrap();
422422
let expected = vec![DeployedPackage::Contract(DeployedContract {
423423
id: ContractId::from_str(
424-
"91c435d6cdb720db92097958163bc43dbc5c4acfbb3d98025039addb9e2da8bb",
424+
"b9443b8e389d42e551b80bb7e94adb4dd37c6985088401940035e36489c90af8",
425425
)
426426
.unwrap(),
427427
proxy: None,
@@ -468,12 +468,12 @@ async fn test_deploy_fresh_proxy() {
468468
node.kill().unwrap();
469469
let impl_contract = DeployedPackage::Contract(DeployedContract {
470470
id: ContractId::from_str(
471-
"91c435d6cdb720db92097958163bc43dbc5c4acfbb3d98025039addb9e2da8bb",
471+
"b9443b8e389d42e551b80bb7e94adb4dd37c6985088401940035e36489c90af8",
472472
)
473473
.unwrap(),
474474
proxy: Some(
475475
ContractId::from_str(
476-
"212c0edca7ddbb762d93a2446083d94df2db059d1f41ad49807223e8249669e5",
476+
"e597d0ef3dc3375402f32bcaa7fc66940f92c31a916e87e7eebb32fcd147d752",
477477
)
478478
.unwrap(),
479479
),

sway-lib-std/src/storage/storage_api.sw

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,13 @@ pub fn write<T>(slot: b256, offset: u64, value: T) {
4343
// Determine how many slots and where the value is to be stored.
4444
let (offset_slot, number_of_slots, place_in_slot) = slot_calculator::<T>(slot, offset);
4545

46+
if __size_of::<T>() % 32 == 0 && place_in_slot == 0 {
47+
// If the value is aligned to the start of a slot and occupies full slots, we can store it directly.
48+
let value_addr = __addr_of::<T>(value);
49+
let _ = __state_store_quad(offset_slot, value_addr, number_of_slots);
50+
return;
51+
}
52+
4653
// Allocate enough memory on the heap for `value` as well as any potential padding required due
4754
// to `offset`.
4855
let padded_value = alloc::<u64>(number_of_slots * 32);
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[[package]]
2+
name = "std"
3+
source = "path+from-root-0377E0F41F094EDB"
4+
5+
[[package]]
6+
name = "storage_slot_sized"
7+
source = "member"
8+
dependencies = ["std"]
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[project]
2+
authors = ["Fuel Labs <[email protected]>"]
3+
entry = "main.sw"
4+
license = "Apache-2.0"
5+
name = "storage_slot_sized"
6+
7+
[dependencies]
8+
std = { path = "../../../../../../../sway-lib-std" }
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
contract;
2+
3+
struct S1 {
4+
f1: u64,
5+
f2: u64,
6+
f3: u64,
7+
f4: u64,
8+
}
9+
10+
impl PartialEq for S1 {
11+
fn eq(self, other: Self) -> bool {
12+
self.f1 == other.f1 && self.f2 == other.f2 && self.f3 == other.f3 && self.f4 == other.f4
13+
}
14+
}
15+
16+
impl Eq for S1 {}
17+
18+
storage {
19+
var1: S1 = S1 { f1: 1, f2: 2, f3: 3, f4: 4 },
20+
var2: (S1, S1) = (S1 { f1: 11, f2: 21, f3: 31, f4: 41 }, S1 { f1: 12, f2: 22, f3: 32, f4: 42 })
21+
}
22+
23+
impl Contract {
24+
#[storage(write)]
25+
fn store_something_1(x: S1) {
26+
storage.var1.write(x);
27+
}
28+
29+
#[storage(read)]
30+
fn check_store_1(x: S1) {
31+
assert_eq(storage.var1.read(), x);
32+
}
33+
34+
#[storage(write)]
35+
fn store_something_2(x: (S1, S1)) {
36+
storage.var2.write(x);
37+
}
38+
39+
#[storage(read)]
40+
fn check_store_2(x: (S1, S1)) {
41+
assert_eq(storage.var2.read(), x);
42+
}
43+
}
44+
45+
#[test]
46+
fn test_store_something() {
47+
let storage_test = abi(StorageSlotSizedAbi, CONTRACT_ID);
48+
let x1 = S1 { f1: 1, f2: 2, f3: 3, f4: 4 };
49+
storage_test.check_store_1(x1);
50+
let x2 = S1 { f1: 2, f2: 3, f3: 4, f4: 5 };
51+
storage_test.store_something_1(x2);
52+
storage_test.check_store_1(x2);
53+
54+
let x3 = (S1 { f1: 11, f2: 21, f3: 31, f4: 41 }, S1 { f1: 12, f2: 22, f3: 32, f4: 42 });
55+
let x4 = (S1 { f1: 111, f2: 211, f3: 311, f4: 411 }, S1 { f1: 121, f2: 221, f3: 321, f4: 421 });
56+
storage_test.check_store_2(x3);
57+
storage_test.store_something_2(x4);
58+
storage_test.check_store_2(x4)
59+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
category = "unit_tests_pass"
2+

test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_basic_storage/src/main.sw

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use basic_storage_abi::{BasicStorage, Quad};
44
#[cfg(experimental_new_encoding = false)]
55
const CONTRACT_ID = 0x94db39f409a31b9f2ebcadeea44378e419208c20de90f5d8e1e33dc1523754cb;
66
#[cfg(experimental_new_encoding = true)]
7-
const CONTRACT_ID = 0x55a636b2843307e245948ea70b113b81d1f30307d4fa6fa0f4bb27c0149afd5c; // AUTO-CONTRACT-ID ../../test_contracts/basic_storage --release
7+
const CONTRACT_ID = 0x841aa8d101ee9b06ff89b72bb5a2bdb46cd6981ba602619fda7424b8b7d47ada; // AUTO-CONTRACT-ID ../../test_contracts/basic_storage --release
88

99
fn main() -> u64 {
1010
let addr = abi(BasicStorage, CONTRACT_ID);

test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_storage_enum/src/main.sw

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use storage_enum_abi::*;
55
#[cfg(experimental_new_encoding = false)]
66
const CONTRACT_ID = 0xc601d11767195485a6654d566c67774134668863d8c797a8c69e8778fb1f89e9;
77
#[cfg(experimental_new_encoding = true)]
8-
const CONTRACT_ID = 0xc7d95c0fdae3df8de6a55f9a8f18c85e2434295d5ca25fe3ccb22fe19658a4d2; // AUTO-CONTRACT-ID ../../test_contracts/storage_enum_contract --release
8+
const CONTRACT_ID = 0x000c798c2f211f31bb2fb6c02fac49dcd461bab4b3c6ade2977ae71537f77406; // AUTO-CONTRACT-ID ../../test_contracts/storage_enum_contract --release
99

1010
fn main() -> u64 {
1111
let caller = abi(StorageEnum, CONTRACT_ID);

test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/storage_access_caller/src/main.sw

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::hash::*;
66
#[cfg(experimental_new_encoding = false)]
77
const CONTRACT_ID = 0x3bc28acd66d327b8c1b9624c1fabfc07e9ffa1b5d71c2832c3bfaaf8f4b805e9;
88
#[cfg(experimental_new_encoding = true)]
9-
const CONTRACT_ID = 0xcd9abae820c4d2570e8f62c3d49a5fed51df1e64ee6c8ba1af7d9a1e91a074e0; // AUTO-CONTRACT-ID ../../test_contracts/storage_access_contract --release
9+
const CONTRACT_ID = 0x4dc4ea62820f5db502781296582ac9e02132eec4452af5a994f92ad2185bb398; // AUTO-CONTRACT-ID ../../test_contracts/storage_access_contract --release
1010

1111
fn main() -> bool {
1212
let caller = abi(StorageAccess, CONTRACT_ID);

0 commit comments

Comments
 (0)