Coverage Report

Created: 2022-08-24 06:31

/src/solidity/liblangutil/EVMVersion.h
Line
Count
Source (jump to first uncovered line)
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 <libevmasm/Instruction.h>
25
26
#include <optional>
27
#include <string>
28
29
#include <boost/operators.hpp>
30
31
32
namespace solidity::langutil
33
{
34
35
/**
36
 * A version specifier of the EVM we want to compile to.
37
 * Defaults to the latest version deployed on Ethereum Mainnet at the time of compiler release.
38
 */
39
class EVMVersion:
40
  boost::less_than_comparable<EVMVersion>,
41
  boost::equality_comparable<EVMVersion>
42
{
43
public:
44
101k
  EVMVersion() = default;
45
46
2
  static EVMVersion homestead() { return {Version::Homestead}; }
47
2
  static EVMVersion tangerineWhistle() { return {Version::TangerineWhistle}; }
48
27.0M
  static EVMVersion spuriousDragon() { return {Version::SpuriousDragon}; }
49
2
  static EVMVersion byzantium() { return {Version::Byzantium}; }
50
16.6M
  static EVMVersion constantinople() { return {Version::Constantinople}; }
51
2
  static EVMVersion petersburg() { return {Version::Petersburg}; }
52
14.3M
  static EVMVersion istanbul() { return {Version::Istanbul}; }
53
2
  static EVMVersion berlin() { return {Version::Berlin}; }
54
0
  static EVMVersion london() { return {Version::London}; }
55
56
  static std::optional<EVMVersion> fromString(std::string const& _version)
57
0
  {
58
0
    for (auto const& v: {homestead(), tangerineWhistle(), spuriousDragon(), byzantium(), constantinople(), petersburg(), istanbul(), berlin(), london()})
59
0
      if (_version == v.name())
60
0
        return v;
61
0
    return std::nullopt;
62
0
  }
63
64
0
  bool operator==(EVMVersion const& _other) const { return m_version == _other.m_version; }
65
58.0M
  bool operator<(EVMVersion const& _other) const { return m_version < _other.m_version; }
66
67
  std::string name() const
68
0
  {
69
0
    switch (m_version)
70
0
    {
71
0
    case Version::Homestead: return "homestead";
72
0
    case Version::TangerineWhistle: return "tangerineWhistle";
73
0
    case Version::SpuriousDragon: return "spuriousDragon";
74
0
    case Version::Byzantium: return "byzantium";
75
0
    case Version::Constantinople: return "constantinople";
76
0
    case Version::Petersburg: return "petersburg";
77
0
    case Version::Istanbul: return "istanbul";
78
0
    case Version::Berlin: return "berlin";
79
0
    case Version::London: return "london";
80
0
    }
81
0
    return "INVALID";
82
0
  }
83
84
  /// Has the RETURNDATACOPY and RETURNDATASIZE opcodes.
85
0
  bool supportsReturndata() const { return *this >= byzantium(); }
86
0
  bool hasStaticCall() const { return *this >= byzantium(); }
87
16.6M
  bool hasBitwiseShifting() const { return *this >= constantinople(); }
88
0
  bool hasCreate2() const { return *this >= constantinople(); }
89
0
  bool hasExtCodeHash() const { return *this >= constantinople(); }
90
0
  bool hasChainID() const { return *this >= istanbul(); }
91
0
  bool hasSelfBalance() const { return *this >= istanbul(); }
92
0
  bool hasBaseFee() const { return *this >= london(); }
93
94
  bool hasOpcode(evmasm::Instruction _opcode) const;
95
96
  /// Whether we have to retain the costs for the call opcode itself (false),
97
  /// or whether we can just forward easily all remaining gas (true).
98
0
  bool canOverchargeGasForCall() const { return *this >= tangerineWhistle(); }
99
100
private:
101
  enum class Version { Homestead, TangerineWhistle, SpuriousDragon, Byzantium, Constantinople, Petersburg, Istanbul, Berlin, London };
102
103
58.0M
  EVMVersion(Version _version): m_version(_version) {}
104
105
  Version m_version = Version::London;
106
};
107
108
}