Coverage Report

Created: 2026-10-26 06:53

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/solidity/liblangutil/EVMVersion.h
Line
Count
Source
1
/*
2
  This file is part of solidity.
3
4
  solidity is free software: you can redistribute it and/or modify
5
  it under the terms of the GNU General Public License as published by
6
  the Free Software Foundation, either version 3 of the License, or
7
  (at your option) any later version.
8
9
  solidity is distributed in the hope that it will be useful,
10
  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
  GNU General Public License for more details.
13
14
  You should have received a copy of the GNU General Public License
15
  along with solidity.  If not, see <http://www.gnu.org/licenses/>.
16
*/
17
// SPDX-License-Identifier: GPL-3.0
18
/**
19
 * EVM versioning.
20
 */
21
22
#pragma once
23
24
#include <libsolutil/Assertions.h>
25
#include <liblangutil//Exceptions.h>
26
27
#include <array>
28
#include <cstddef>
29
#include <cstdint>
30
#include <optional>
31
#include <string>
32
33
namespace solidity::evmasm
34
{
35
/// Virtual machine bytecode instruction. Forward declared from libevmasm/Instruction.h
36
enum class Instruction: uint8_t;
37
}
38
39
namespace solidity::langutil
40
{
41
42
/**
43
 * A version specifier of the EVM we want to compile to.
44
 * Defaults to the latest version deployed on Ethereum Mainnet at the time of compiler release.
45
 */
46
class EVMVersion
47
{
48
public:
49
158M
  EVMVersion() = default;
50
51
1.42k
  static EVMVersion current() { return {currentVersion}; }
52
53
1.20M
  static EVMVersion constexpr homestead() { return {Version::Homestead}; }
54
345k
  static EVMVersion constexpr tangerineWhistle() { return {Version::TangerineWhistle}; }
55
57.3M
  static EVMVersion constexpr spuriousDragon() { return {Version::SpuriousDragon}; }
56
33.5M
  static EVMVersion constexpr byzantium() { return {Version::Byzantium}; }
57
73.4M
  static EVMVersion constexpr constantinople() { return {Version::Constantinople}; }
58
13.9k
  static EVMVersion constexpr petersburg() { return {Version::Petersburg}; }
59
70.4M
  static EVMVersion constexpr istanbul() { return {Version::Istanbul}; }
60
26.0k
  static EVMVersion constexpr berlin() { return {Version::Berlin}; }
61
561k
  static EVMVersion constexpr london() { return {Version::London}; }
62
847k
  static EVMVersion constexpr paris() { return {Version::Paris}; }
63
309M
  static EVMVersion constexpr shanghai() { return {Version::Shanghai}; }
64
43.1M
  static EVMVersion constexpr cancun() { return {Version::Cancun}; }
65
14.1k
  static EVMVersion constexpr prague() { return {Version::Prague}; }
66
553k
  static EVMVersion constexpr osaka() { return {Version::Osaka}; }
67
536k
  static EVMVersion constexpr amsterdam() { return {Version::Amsterdam}; }
68
0
  static EVMVersion constexpr future() { return {Version::Future}; }
69
70
0
  static auto constexpr allVersions() {
71
0
    return std::array{
72
0
      homestead(),
73
0
      tangerineWhistle(),
74
0
      spuriousDragon(),
75
0
      byzantium(),
76
0
      constantinople(),
77
0
      petersburg(),
78
0
      istanbul(),
79
0
      berlin(),
80
0
      london(),
81
0
      paris(),
82
0
      shanghai(),
83
0
      cancun(),
84
0
      prague(),
85
0
      osaka(),
86
0
      amsterdam(),
87
0
      future(),
88
0
    };
89
0
  }
90
91
  static std::optional<EVMVersion> fromString(std::string const& _version)
92
0
  {
93
0
    for (auto const& v: allVersions())
94
0
      if (_version == v.name())
95
0
        return v;
96
0
    return std::nullopt;
97
0
  }
98
99
0
  bool isExperimental() const {
100
0
    solAssert(Version::Future > currentVersion);
101
0
    return m_version > currentVersion;
102
0
  }
Unexecuted instantiation: solidity::langutil::EVMVersion::isExperimental() const
Unexecuted instantiation: solidity::langutil::EVMVersion::isExperimental() const
103
104
1.54G
  auto operator<=>(EVMVersion const&) const = default;
105
106
  std::string name() const
107
81.5k
  {
108
81.5k
    switch (m_version)
109
81.5k
    {
110
3.85k
    case Version::Homestead: return "homestead";
111
1.82k
    case Version::TangerineWhistle: return "tangerineWhistle";
112
1.76k
    case Version::SpuriousDragon: return "spuriousDragon";
113
1.51k
    case Version::Byzantium: return "byzantium";
114
1.63k
    case Version::Constantinople: return "constantinople";
115
1.51k
    case Version::Petersburg: return "petersburg";
116
1.55k
    case Version::Istanbul: return "istanbul";
117
1.41k
    case Version::Berlin: return "berlin";
118
1.39k
    case Version::London: return "london";
119
1.52k
    case Version::Paris: return "paris";
120
1.53k
    case Version::Shanghai: return "shanghai";
121
1.42k
    case Version::Cancun: return "cancun";
122
1.43k
    case Version::Prague: return "prague";
123
56.2k
    case Version::Osaka: return "osaka";
124
1.47k
    case Version::Amsterdam: return "amsterdam";
125
1.50k
    case Version::Future: return "@future";
126
81.5k
    }
127
0
    util::unreachable();
128
0
  }
129
130
  /// Has the RETURNDATACOPY and RETURNDATASIZE opcodes.
131
16.9M
  bool supportsReturndata() const { return *this >= byzantium(); }
132
16.4M
  bool hasStaticCall() const { return *this >= byzantium(); }
133
56.7M
  bool hasBitwiseShifting() const { return *this >= constantinople(); }
134
536k
  bool hasCLZ() const { return *this >= osaka(); }
135
16.4M
  bool hasCreate2() const { return *this >= constantinople(); }
136
282k
  bool hasExtCodeHash() const { return *this >= constantinople(); }
137
288k
  bool hasChainID() const { return *this >= istanbul(); }
138
622k
  bool hasSelfBalance() const { return *this >= istanbul(); }
139
279k
  bool hasBaseFee() const { return *this >= london(); }
140
271k
  bool hasBlobBaseFee() const { return *this >= cancun(); }
141
39
  bool hasPrevRandao() const { return *this >= paris(); }
142
309M
  bool hasPush0() const { return *this >= shanghai(); }
143
327k
  bool hasBlobHash() const { return *this >= cancun(); }
144
300k
  bool hasMcopy() const { return *this >= cancun(); }
145
1.23M
  bool supportsTransientStorage() const { return *this >= cancun(); }
146
536k
  bool hasSlotNum() const { return *this >= amsterdam(); }
147
61.5M
  constexpr size_t reachableStackDepth() const { return 16; }
148
149
  bool hasOpcode(evmasm::Instruction _opcode) const;
150
151
  /// Whether we have to retain the costs for the call opcode itself (false),
152
  /// or whether we can just forward easily all remaining gas (true).
153
330k
  bool canOverchargeGasForCall() const { return *this >= tangerineWhistle(); }
154
155
private:
156
  enum class Version {
157
    Homestead,
158
    TangerineWhistle,
159
    SpuriousDragon,
160
    Byzantium,
161
    Constantinople,
162
    Petersburg,
163
    Istanbul,
164
    Berlin,
165
    London,
166
    Paris,
167
    Shanghai,
168
    Cancun,
169
    Prague,
170
    Osaka,
171
    Amsterdam,
172
    Future,
173
  };
174
  static auto constexpr currentVersion = Version::Osaka;
175
176
591M
  constexpr EVMVersion(Version _version): m_version(_version) {}
177
178
  Version m_version = currentVersion;
179
};
180
181
}