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 	EVMVersion() = default;
45 
homestead()46 	static EVMVersion homestead() { return {Version::Homestead}; }
tangerineWhistle()47 	static EVMVersion tangerineWhistle() { return {Version::TangerineWhistle}; }
spuriousDragon()48 	static EVMVersion spuriousDragon() { return {Version::SpuriousDragon}; }
byzantium()49 	static EVMVersion byzantium() { return {Version::Byzantium}; }
constantinople()50 	static EVMVersion constantinople() { return {Version::Constantinople}; }
petersburg()51 	static EVMVersion petersburg() { return {Version::Petersburg}; }
istanbul()52 	static EVMVersion istanbul() { return {Version::Istanbul}; }
berlin()53 	static EVMVersion berlin() { return {Version::Berlin}; }
london()54 	static EVMVersion london() { return {Version::London}; }
55 
fromString(std::string const & _version)56 	static std::optional<EVMVersion> fromString(std::string const& _version)
57 	{
58 		for (auto const& v: {homestead(), tangerineWhistle(), spuriousDragon(), byzantium(), constantinople(), petersburg(), istanbul(), berlin(), london()})
59 			if (_version == v.name())
60 				return v;
61 		return std::nullopt;
62 	}
63 
64 	bool operator==(EVMVersion const& _other) const { return m_version == _other.m_version; }
65 	bool operator<(EVMVersion const& _other) const { return m_version < _other.m_version; }
66 
name()67 	std::string name() const
68 	{
69 		switch (m_version)
70 		{
71 		case Version::Homestead: return "homestead";
72 		case Version::TangerineWhistle: return "tangerineWhistle";
73 		case Version::SpuriousDragon: return "spuriousDragon";
74 		case Version::Byzantium: return "byzantium";
75 		case Version::Constantinople: return "constantinople";
76 		case Version::Petersburg: return "petersburg";
77 		case Version::Istanbul: return "istanbul";
78 		case Version::Berlin: return "berlin";
79 		case Version::London: return "london";
80 		}
81 		return "INVALID";
82 	}
83 
84 	/// Has the RETURNDATACOPY and RETURNDATASIZE opcodes.
supportsReturndata()85 	bool supportsReturndata() const { return *this >= byzantium(); }
hasStaticCall()86 	bool hasStaticCall() const { return *this >= byzantium(); }
hasBitwiseShifting()87 	bool hasBitwiseShifting() const { return *this >= constantinople(); }
hasCreate2()88 	bool hasCreate2() const { return *this >= constantinople(); }
hasExtCodeHash()89 	bool hasExtCodeHash() const { return *this >= constantinople(); }
hasChainID()90 	bool hasChainID() const { return *this >= istanbul(); }
hasSelfBalance()91 	bool hasSelfBalance() const { return *this >= istanbul(); }
hasBaseFee()92 	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).
canOverchargeGasForCall()98 	bool canOverchargeGasForCall() const { return *this >= tangerineWhistle(); }
99 
100 private:
101 	enum class Version { Homestead, TangerineWhistle, SpuriousDragon, Byzantium, Constantinople, Petersburg, Istanbul, Berlin, London };
102 
EVMVersion(Version _version)103 	EVMVersion(Version _version): m_version(_version) {}
104 
105 	Version m_version = Version::London;
106 };
107 
108 }
109