neo_solidity/cli/bytecode/bytecode_helpers/storage/
state.rs1fn emit_load_state(bytecode: &mut Vec<u8>, module: &ir::Module, index: usize) {
2 let key = module
3 .state_variables
4 .get(index)
5 .map(|state| state.storage_key.as_slice())
6 .unwrap_or(&[]);
7 let value_type = module.state_variables.get(index).map(|state| &state.ty);
8
9 push_data(bytecode, key);
10 emit_syscall(bytecode, "System.Storage.GetContext");
11 emit_syscall(bytecode, "System.Storage.Get");
12 if let Some(ty) = value_type {
13 emit_coerce_storage_value(bytecode, ty);
14 }
15}
16
17fn emit_store_state(bytecode: &mut Vec<u8>, module: &ir::Module, index: usize) {
18 let key = module
19 .state_variables
20 .get(index)
21 .map(|state| state.storage_key.as_slice())
22 .unwrap_or(&[]);
23
24 push_data(bytecode, key);
25 emit_syscall(bytecode, "System.Storage.GetContext");
26 emit_syscall(bytecode, "System.Storage.Put");
28}
29
30fn emit_coerce_storage_value(bytecode: &mut Vec<u8>, ty: &ValueType) {
31 fn with_null_default(
32 bytecode: &mut Vec<u8>,
33 default_value: impl Fn(&mut Vec<u8>),
34 not_null: impl FnOnce(&mut Vec<u8>),
35 ) {
36 bytecode.push(0x4A); bytecode.push(0xD8); let jmp_not_null_pos = bytecode.len();
43 bytecode.push(0x27); let jmp_not_null_operand = bytecode.len();
45 bytecode.extend_from_slice(&[0, 0, 0, 0]);
46
47 bytecode.push(0x45); default_value(bytecode);
50
51 let jmp_end_pos = bytecode.len();
53 bytecode.push(0x23); let jmp_end_operand = bytecode.len();
55 bytecode.extend_from_slice(&[0, 0, 0, 0]);
56
57 let not_null_pos = bytecode.len();
59 bytecode.push(0x4A); bytecode.push(0xCA); bytecode.push(0x10); bytecode.push(0x97); let jmp_not_missing_pos = bytecode.len();
69 bytecode.push(0x27); let jmp_not_missing_operand = bytecode.len();
71 bytecode.extend_from_slice(&[0, 0, 0, 0]);
72
73 bytecode.push(0x45); default_value(bytecode);
76
77 let jmp_end2_pos = bytecode.len();
79 bytecode.push(0x23); let jmp_end2_operand = bytecode.len();
81 bytecode.extend_from_slice(&[0, 0, 0, 0]);
82
83 let not_missing_pos = bytecode.len();
85 not_null(bytecode);
86
87 let end_pos = bytecode.len();
89
90 let rel_not_null = (not_null_pos as i32)
91 .checked_sub(jmp_not_null_pos as i32)
92 .unwrap_or(0);
93 bytecode[jmp_not_null_operand..jmp_not_null_operand + 4]
94 .copy_from_slice(&rel_not_null.to_le_bytes());
95
96 let rel_not_missing = (not_missing_pos as i32)
97 .checked_sub(jmp_not_missing_pos as i32)
98 .unwrap_or(0);
99 bytecode[jmp_not_missing_operand..jmp_not_missing_operand + 4]
100 .copy_from_slice(&rel_not_missing.to_le_bytes());
101
102 let rel_end = (end_pos as i32).checked_sub(jmp_end_pos as i32).unwrap_or(0);
103 bytecode[jmp_end_operand..jmp_end_operand + 4].copy_from_slice(&rel_end.to_le_bytes());
104
105 let rel_end2 = (end_pos as i32).checked_sub(jmp_end2_pos as i32).unwrap_or(0);
106 bytecode[jmp_end2_operand..jmp_end2_operand + 4].copy_from_slice(&rel_end2.to_le_bytes());
107 }
108
109 match ty {
110 ValueType::Integer { .. } => {
111 with_null_default(
112 bytecode,
113 |bytecode| bytecode.push(0x10), |bytecode| {
115 bytecode.push(0x10); bytecode.push(0x9E); },
119 );
120 }
121 ValueType::Boolean => {
122 with_null_default(
123 bytecode,
124 |bytecode| bytecode.push(0x09), |bytecode| {
126 bytecode.push(0xB1); },
129 );
130 }
131 ValueType::String => {
132 with_null_default(bytecode, |bytecode| push_data(bytecode, &[]), |_bytecode| {});
133 }
134 ValueType::Address => {
135 with_null_default(bytecode, |bytecode| push_data(bytecode, &[0u8; 20]), |_bytecode| {});
136 }
137 ValueType::ByteArray { fixed_len } => {
138 let default_bytes = fixed_len
139 .map(|len| vec![0u8; len as usize])
140 .unwrap_or_default();
141 with_null_default(bytecode, |bytecode| push_data(bytecode, &default_bytes), |_bytecode| {});
142 }
143 ValueType::Array(_) => {
144 with_null_default(
145 bytecode,
146 |bytecode| bytecode.push(0x10), |bytecode| {
148 bytecode.push(0x10); bytecode.push(0x9E); },
153 );
154 }
155 _ => {}
156 }
157}