forked from bluealloy/revm
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsystem.rs
141 lines (124 loc) · 4.96 KB
/
system.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
use crate::{
gas,
primitives::{Spec, B256, KECCAK_EMPTY, U256},
Host, InstructionResult, Interpreter,
};
pub fn keccak256<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
pop!(interpreter, from, len);
let len = as_usize_or_fail!(interpreter, len);
gas_or_fail!(interpreter, gas::keccak256_cost(len as u64));
let hash = if len == 0 {
KECCAK_EMPTY
} else {
let from = as_usize_or_fail!(interpreter, from);
shared_memory_resize!(interpreter, from, len);
crate::primitives::keccak256(interpreter.shared_memory.slice(from, len))
};
push_b256!(interpreter, hash);
}
pub fn address<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::BASE);
push_b256!(interpreter, B256::from(interpreter.contract.address));
}
pub fn caller<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::BASE);
push_b256!(interpreter, B256::from(interpreter.contract.caller));
}
pub fn codesize<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::BASE);
push!(interpreter, U256::from(interpreter.contract.bytecode.len()));
}
pub fn codecopy<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
pop!(interpreter, memory_offset, code_offset, len);
let len = as_usize_or_fail!(interpreter, len);
gas_or_fail!(interpreter, gas::verylowcopy_cost(len as u64));
if len == 0 {
return;
}
let memory_offset = as_usize_or_fail!(interpreter, memory_offset);
let code_offset = as_usize_saturated!(code_offset);
shared_memory_resize!(interpreter, memory_offset, len);
// Safety: set_data is unsafe function and memory_resize ensures us that it is safe to call it
interpreter.shared_memory.set_data(
memory_offset,
code_offset,
len,
interpreter.contract.bytecode.original_bytecode_slice(),
);
}
pub fn calldataload<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::VERYLOW);
pop!(interpreter, index);
let index = as_usize_saturated!(index);
let load = if index < interpreter.contract.input.len() {
let n = 32.min(interpreter.contract.input.len() - index);
let mut bytes = [0u8; 32];
// SAFETY: n <= len - index -> index + n <= len
let src = unsafe { interpreter.contract.input.get_unchecked(index..index + n) };
bytes[..n].copy_from_slice(src);
U256::from_be_bytes(bytes)
} else {
U256::ZERO
};
push!(interpreter, load);
}
pub fn calldatasize<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::BASE);
push!(interpreter, U256::from(interpreter.contract.input.len()));
}
pub fn callvalue<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::BASE);
push!(interpreter, interpreter.contract.value);
}
pub fn calldatacopy<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
pop!(interpreter, memory_offset, data_offset, len);
let len = as_usize_or_fail!(interpreter, len);
gas_or_fail!(interpreter, gas::verylowcopy_cost(len as u64));
if len == 0 {
return;
}
let memory_offset = as_usize_or_fail!(interpreter, memory_offset);
let data_offset = as_usize_saturated!(data_offset);
shared_memory_resize!(interpreter, memory_offset, len);
// Safety: set_data is unsafe function and memory_resize ensures us that it is safe to call it
interpreter.shared_memory.set_data(
memory_offset,
data_offset,
len,
&interpreter.contract.input,
);
}
/// EIP-211: New opcodes: RETURNDATASIZE and RETURNDATACOPY
pub fn returndatasize<H: Host, SPEC: Spec>(interpreter: &mut Interpreter, _host: &mut H) {
check!(interpreter, BYZANTIUM);
gas!(interpreter, gas::BASE);
push!(
interpreter,
U256::from(interpreter.return_data_buffer.len())
);
}
/// EIP-211: New opcodes: RETURNDATASIZE and RETURNDATACOPY
pub fn returndatacopy<H: Host, SPEC: Spec>(interpreter: &mut Interpreter, _host: &mut H) {
check!(interpreter, BYZANTIUM);
pop!(interpreter, memory_offset, offset, len);
let len = as_usize_or_fail!(interpreter, len);
gas_or_fail!(interpreter, gas::verylowcopy_cost(len as u64));
let data_offset = as_usize_saturated!(offset);
let (data_end, overflow) = data_offset.overflowing_add(len);
if overflow || data_end > interpreter.return_data_buffer.len() {
interpreter.instruction_result = InstructionResult::OutOfOffset;
return;
}
if len != 0 {
let memory_offset = as_usize_or_fail!(interpreter, memory_offset);
shared_memory_resize!(interpreter, memory_offset, len);
interpreter.shared_memory.set(
memory_offset,
&interpreter.return_data_buffer[data_offset..data_end],
);
}
}
pub fn gas<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::BASE);
push!(interpreter, U256::from(interpreter.gas.remaining()));
}