revm_interpreter/instructions/
block_info.rs

1use crate::{
2    gas,
3    interpreter_types::{InterpreterTypes, RuntimeFlag, StackTr},
4    Host,
5};
6use primitives::{hardfork::SpecId::*, U256};
7
8use crate::InstructionContext;
9
10/// EIP-1344: ChainID opcode
11pub fn chainid<WIRE: InterpreterTypes, H: Host + ?Sized>(context: InstructionContext<'_, H, WIRE>) {
12    check!(context.interpreter, ISTANBUL);
13    gas!(context.interpreter, gas::BASE);
14    push!(context.interpreter, context.host.chain_id());
15}
16
17/// Implements the COINBASE instruction.
18///
19/// Pushes the current block's beneficiary address onto the stack.
20pub fn coinbase<WIRE: InterpreterTypes, H: Host + ?Sized>(
21    context: InstructionContext<'_, H, WIRE>,
22) {
23    gas!(context.interpreter, gas::BASE);
24    push!(
25        context.interpreter,
26        context.host.beneficiary().into_word().into()
27    );
28}
29
30/// Implements the TIMESTAMP instruction.
31///
32/// Pushes the current block's timestamp onto the stack.
33pub fn timestamp<WIRE: InterpreterTypes, H: Host + ?Sized>(
34    context: InstructionContext<'_, H, WIRE>,
35) {
36    gas!(context.interpreter, gas::BASE);
37    push!(context.interpreter, context.host.timestamp());
38}
39
40/// Implements the NUMBER instruction.
41///
42/// Pushes the current block number onto the stack.
43pub fn block_number<WIRE: InterpreterTypes, H: Host + ?Sized>(
44    context: InstructionContext<'_, H, WIRE>,
45) {
46    gas!(context.interpreter, gas::BASE);
47    push!(context.interpreter, U256::from(context.host.block_number()));
48}
49
50/// Implements the DIFFICULTY/PREVRANDAO instruction.
51///
52/// Pushes the block difficulty (pre-merge) or prevrandao (post-merge) onto the stack.
53pub fn difficulty<WIRE: InterpreterTypes, H: Host + ?Sized>(
54    context: InstructionContext<'_, H, WIRE>,
55) {
56    gas!(context.interpreter, gas::BASE);
57    if context
58        .interpreter
59        .runtime_flag
60        .spec_id()
61        .is_enabled_in(MERGE)
62    {
63        // Unwrap is safe as this fields is checked in validation handler.
64        push!(context.interpreter, context.host.prevrandao().unwrap());
65    } else {
66        push!(context.interpreter, context.host.difficulty());
67    }
68}
69
70/// Implements the GASLIMIT instruction.
71///
72/// Pushes the current block's gas limit onto the stack.
73pub fn gaslimit<WIRE: InterpreterTypes, H: Host + ?Sized>(
74    context: InstructionContext<'_, H, WIRE>,
75) {
76    gas!(context.interpreter, gas::BASE);
77    push!(context.interpreter, context.host.gas_limit());
78}
79
80/// EIP-3198: BASEFEE opcode
81pub fn basefee<WIRE: InterpreterTypes, H: Host + ?Sized>(context: InstructionContext<'_, H, WIRE>) {
82    check!(context.interpreter, LONDON);
83    gas!(context.interpreter, gas::BASE);
84    push!(context.interpreter, context.host.basefee());
85}
86
87/// EIP-7516: BLOBBASEFEE opcode
88pub fn blob_basefee<WIRE: InterpreterTypes, H: Host + ?Sized>(
89    context: InstructionContext<'_, H, WIRE>,
90) {
91    check!(context.interpreter, CANCUN);
92    gas!(context.interpreter, gas::BASE);
93    push!(context.interpreter, context.host.blob_gasprice());
94}