From 8757e0aa115e4e5fe484f8e89589cb81d71e0518 Mon Sep 17 00:00:00 2001 From: hrkrshnn Date: Sun, 9 Apr 2023 15:42:53 +0200 Subject: [PATCH] feat: add support for `push0` in libevmasm See https://eips.ethereum.org/EIPS/eip-3855 Note: `push0` costs 2 gas, i.e., `Tier::Base` unlike other pushes. --- libevmasm/Instruction.cpp | 2 ++ libevmasm/Instruction.h | 9 +++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/libevmasm/Instruction.cpp b/libevmasm/Instruction.cpp index 418a6e185..2c313fd75 100644 --- a/libevmasm/Instruction.cpp +++ b/libevmasm/Instruction.cpp @@ -94,6 +94,7 @@ std::map const solidity::evmasm::c_instructions = { "MSIZE", Instruction::MSIZE }, { "GAS", Instruction::GAS }, { "JUMPDEST", Instruction::JUMPDEST }, + { "PUSH0", Instruction::PUSH0 }, { "PUSH1", Instruction::PUSH1 }, { "PUSH2", Instruction::PUSH2 }, { "PUSH3", Instruction::PUSH3 }, @@ -242,6 +243,7 @@ static std::map const c_instructionInfo = { Instruction::MSIZE, { "MSIZE", 0, 0, 1, false, Tier::Base } }, { Instruction::GAS, { "GAS", 0, 0, 1, false, Tier::Base } }, { Instruction::JUMPDEST, { "JUMPDEST", 0, 0, 0, true, Tier::Special } }, + { Instruction::PUSH0, { "PUSH0", 0, 0, 1, false, Tier::Base } }, { Instruction::PUSH1, { "PUSH1", 1, 0, 1, false, Tier::VeryLow } }, { Instruction::PUSH2, { "PUSH2", 2, 0, 1, false, Tier::VeryLow } }, { Instruction::PUSH3, { "PUSH3", 3, 0, 1, false, Tier::VeryLow } }, diff --git a/libevmasm/Instruction.h b/libevmasm/Instruction.h index 48ee37b5c..2fddb11d8 100644 --- a/libevmasm/Instruction.h +++ b/libevmasm/Instruction.h @@ -103,6 +103,7 @@ enum class Instruction: uint8_t GAS, ///< get the amount of available gas JUMPDEST, ///< set a potential jump destination + PUSH0 = 0x5f, ///< place the value 0 on stack PUSH1 = 0x60, ///< place 1 byte item on stack PUSH2, ///< place 2 byte item on stack PUSH3, ///< place 3 byte item on stack @@ -207,7 +208,7 @@ constexpr bool isCallInstruction(Instruction _inst) noexcept /// @returns true if the instruction is a PUSH inline bool isPushInstruction(Instruction _inst) { - return Instruction::PUSH1 <= _inst && _inst <= Instruction::PUSH32; + return Instruction::PUSH0 <= _inst && _inst <= Instruction::PUSH32; } /// @returns true if the instruction is a DUP @@ -231,7 +232,7 @@ inline bool isLogInstruction(Instruction _inst) /// @returns the number of PUSH Instruction _inst inline unsigned getPushNumber(Instruction _inst) { - return static_cast(_inst) - unsigned(Instruction::PUSH1) + 1; + return static_cast(_inst) - unsigned(Instruction::PUSH0); } /// @returns the number of DUP Instruction _inst @@ -255,8 +256,8 @@ inline unsigned getLogNumber(Instruction _inst) /// @returns the PUSH<_number> instruction inline Instruction pushInstruction(unsigned _number) { - assertThrow(1 <= _number && _number <= 32, InvalidOpcode, std::string("Invalid PUSH instruction requested (") + std::to_string(_number) + ")."); - return Instruction(unsigned(Instruction::PUSH1) + _number - 1); + assertThrow(_number <= 32, InvalidOpcode, std::string("Invalid PUSH instruction requested (") + std::to_string(_number) + ")."); + return Instruction(unsigned(Instruction::PUSH0) + _number); } /// @returns the DUP<_number> instruction