aboutsummaryrefslogtreecommitdiffstats
path: root/liblangutil/EVMVersion.h
blob: 21889bd9c5cb73a2c051cc942421de12eea3f990 (plain) (blame)
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
/*
    This file is part of solidity.

    solidity is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    solidity is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with solidity.  If not, see <http://www.gnu.org/licenses/>.
*/
/**
 * EVM versioning.
 */

#pragma once

#include <string>

#include <boost/optional.hpp>
#include <boost/operators.hpp>

namespace dev
{
namespace solidity
{

/**
 * A version specifier of the EVM we want to compile to.
 * Defaults to the latest version.
 */
class EVMVersion:
    boost::less_than_comparable<EVMVersion>,
    boost::equality_comparable<EVMVersion>
{
public:
    EVMVersion() = default;

    static EVMVersion homestead() { return {Version::Homestead}; }
    static EVMVersion tangerineWhistle() { return {Version::TangerineWhistle}; }
    static EVMVersion spuriousDragon() { return {Version::SpuriousDragon}; }
    static EVMVersion byzantium() { return {Version::Byzantium}; }
    static EVMVersion constantinople() { return {Version::Constantinople}; }

    static boost::optional<EVMVersion> fromString(std::string const& _version)
    {
        for (auto const& v: {homestead(), tangerineWhistle(), spuriousDragon(), byzantium(), constantinople()})
            if (_version == v.name())
                return v;
        return {};
    }

    bool operator==(EVMVersion const& _other) const { return m_version == _other.m_version; }
    bool operator<(EVMVersion const& _other) const { return m_version < _other.m_version; }

    std::string name() const
    {
        switch (m_version)
        {
        case Version::Homestead: return "homestead";
        case Version::TangerineWhistle: return "tangerineWhistle";
        case Version::SpuriousDragon: return "spuriousDragon";
        case Version::Byzantium: return "byzantium";
        case Version::Constantinople: return "constantinople";
        }
        return "INVALID";
    }

    /// Has the RETURNDATACOPY and RETURNDATASIZE opcodes.
    bool supportsReturndata() const { return *this >= byzantium(); }
    bool hasStaticCall() const { return *this >= byzantium(); }
    bool hasBitwiseShifting() const { return *this >= constantinople(); }
    bool hasCreate2() const { return *this >= constantinople(); }

    /// Whether we have to retain the costs for the call opcode itself (false),
    /// or whether we can just forward easily all remaining gas (true).
    bool canOverchargeGasForCall() const { return *this >= tangerineWhistle(); }

private:
    enum class Version { Homestead, TangerineWhistle, SpuriousDragon, Byzantium, Constantinople };

    EVMVersion(Version _version): m_version(_version) {}

    Version m_version = Version::Byzantium;
};


}
}