neo_solidity/cli/bytecode/bytecode_helpers/storage/
mapping.rs

1fn emit_serialize_key(
2    bytecode: &mut Vec<u8>,
3    _key_type: &ValueType,
4    use_callt: bool,
5    token_patches: &mut Vec<MethodTokenPatch>,
6) {
7    emit_native_contract_call(
8        bytecode,
9        ir::NativeContract::StdLib,
10        "serialize",
11        1,
12        use_callt,
13        token_patches,
14    );
15}
16
17fn emit_mapping_slot(
18    bytecode: &mut Vec<u8>,
19    module: &ir::Module,
20    state_index: usize,
21    key_types: &[ValueType],
22    use_callt: bool,
23    token_patches: &mut Vec<MethodTokenPatch>,
24) {
25    let base_slot = module
26        .state_variables
27        .get(state_index)
28        .map(|state| state.storage_key.clone())
29        .unwrap_or_else(|| vec![0u8; 32]);
30
31    push_data(bytecode, &base_slot);
32
33    for key_type in key_types {
34        bytecode.push(0x50); // swap slot <-> key
35        emit_serialize_key(bytecode, key_type, use_callt, token_patches);
36        bytecode.push(0x50); // swap key_bytes <-> slot
37        bytecode.push(0x8B); // concatenate key and slot
38        emit_native_contract_call(
39            bytecode,
40            ir::NativeContract::CryptoLib,
41            "keccak256",
42            1,
43            use_callt,
44            token_patches,
45        );
46    }
47}
48
49fn emit_struct_field_slot(
50    bytecode: &mut Vec<u8>,
51    module: &ir::Module,
52    state_index: usize,
53    key_types: &[ValueType],
54    field_keys: &[[u8; 32]],
55    use_callt: bool,
56    token_patches: &mut Vec<MethodTokenPatch>,
57) {
58    emit_mapping_slot(
59        bytecode,
60        module,
61        state_index,
62        key_types,
63        use_callt,
64        token_patches,
65    );
66    for field_key in field_keys {
67        push_data(bytecode, field_key);
68        bytecode.push(0x50); // swap slot and field key bytes
69        bytecode.push(0x8B); // concatenate
70        emit_native_contract_call(
71            bytecode,
72            ir::NativeContract::CryptoLib,
73            "keccak256",
74            1,
75            use_callt,
76            token_patches,
77        );
78    }
79}
80
81fn emit_load_mapping(
82    bytecode: &mut Vec<u8>,
83    module: &ir::Module,
84    state_index: usize,
85    key_types: &[ValueType],
86    use_callt: bool,
87    token_patches: &mut Vec<MethodTokenPatch>,
88) {
89    emit_mapping_slot(
90        bytecode,
91        module,
92        state_index,
93        key_types,
94        use_callt,
95        token_patches,
96    );
97    emit_syscall(bytecode, "System.Storage.GetContext");
98    emit_syscall(bytecode, "System.Storage.Get");
99    if let Some(ir::StateVariable {
100        ty: ValueType::Mapping { value, .. },
101        ..
102    }) = module.state_variables.get(state_index)
103    {
104        emit_coerce_storage_value(bytecode, value);
105    }
106}
107
108fn emit_store_mapping(
109    bytecode: &mut Vec<u8>,
110    module: &ir::Module,
111    state_index: usize,
112    key_types: &[ValueType],
113    use_callt: bool,
114    token_patches: &mut Vec<MethodTokenPatch>,
115) {
116    emit_mapping_slot(
117        bytecode,
118        module,
119        state_index,
120        key_types,
121        use_callt,
122        token_patches,
123    );
124    emit_syscall(bytecode, "System.Storage.GetContext");
125    emit_syscall(bytecode, "System.Storage.Put");
126}