Skip to content

Instantly share code, notes, and snippets.

@tavakyan
Created November 9, 2023 20:14
Show Gist options
  • Save tavakyan/3652f1f726e0fe6e7704fb19cad4acf3 to your computer and use it in GitHub Desktop.
Save tavakyan/3652f1f726e0fe6e7704fb19cad4acf3 to your computer and use it in GitHub Desktop.

Revisions

  1. tavakyan created this gist Nov 9, 2023.
    136 changes: 136 additions & 0 deletions EvmOpcodes.sol
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,136 @@
    pragma solidity ^0.8.19;

    /**
    * @title EvmOpcodes contract to look up gas for an operation
    * @dev Library for managing EVM opcodes, including their gas costs.
    */
    contract EvmOpcodes {
    // Mapping from opcode name to its gas cost
    mapping(string => uint) private opcodes;

    /**
    * @dev Constructor to initialize the opcodes with their respective gas costs.
    */
    constructor() {
    opcodes["STOP"] = 0;
    opcodes["ADD"] = 3;
    opcodes["MUL"] = 5;
    opcodes["SUB"] = 3;
    opcodes["DIV"] = 5;
    opcodes["SDIV"] = 5;
    opcodes["MOD"] = 5;
    opcodes["SMOD"] = 5;
    opcodes["ADDMOD"] = 8;
    opcodes["MULMOD"] = 8;
    opcodes["EXP"] = 10;
    opcodes["SIGNEXTEND"] = 5;
    opcodes["LT"] = 3;
    opcodes["GT"] = 3;
    opcodes["SLT"] = 3;
    opcodes["SGT"] = 3;
    opcodes["EQ"] = 3;
    opcodes["ISZERO"] = 3;
    opcodes["AND"] = 3;
    opcodes["OR"] = 3;
    opcodes["XOR"] = 3;
    opcodes["NOT"] = 3;
    opcodes["BYTE"] = 3;
    opcodes["SHL"] = 3;
    opcodes["SHR"] = 3;
    opcodes["SAR"] = 3;
    opcodes["SHA3"] = 30;
    opcodes["ADDRESS"] = 2;
    opcodes["BALANCE"] = 100;
    opcodes["ORIGIN"] = 2;
    opcodes["CALLER"] = 2;
    opcodes["CALLVALUE"] = 2;
    opcodes["CALLDATALOAD"] = 3;
    opcodes["CALLDATASIZE"] = 2;
    opcodes["CALLDATACOPY"] = 3;
    opcodes["CODESIZE"] = 2;
    opcodes["CODECOPY"] = 3;
    opcodes["GASPRICE"] = 2;
    opcodes["EXTCODESIZE"] = 100;
    opcodes["EXTCODECOPY"] = 100;
    opcodes["RETURNDATASIZE"] = 2;
    opcodes["RETURNDATACOPY"] = 3;
    opcodes["EXTCODEHASH"] = 100;
    opcodes["BLOCKHASH"] = 20;
    opcodes["COINBASE"] = 2;
    opcodes["TIMESTAMP"] = 2;
    opcodes["NUMBER"] = 2;
    opcodes["PREVRANDAO"] = 2;
    opcodes["GASLIMIT"] = 2;
    opcodes["CHAINID"] = 2;
    opcodes["SELFBALANCE"] = 5;
    opcodes["BASEFEE"] = 2;
    opcodes["POP"] = 2;
    opcodes["MLOAD"] = 3;
    opcodes["MSTORE"] = 3;
    opcodes["MSTORE8"] = 3;
    opcodes["SLOAD"] = 100;
    opcodes["SSTORE"] = 100;
    opcodes["JUMP"] = 8;
    opcodes["JUMPI"] = 10;
    opcodes["PC"] = 2;
    opcodes["MSIZE"] = 2;
    opcodes["GAS"] = 2;
    opcodes["JUMPDEST"] = 1;

    // Expanding PUSH1 to PUSH32
    for (uint i = 1; i <= 32; ++i) {
    opcodes[string(abi.encodePacked("PUSH", i.toString()))] = 3;
    }

    // Expanding DUP1 to DUP16
    for (uint i = 1; i <= 16; ++i) {
    opcodes[string(abi.encodePacked("DUP", i.toString()))] = 3;
    }

    // Expanding SWAP1 to SWAP16
    for (uint i = 1; i <= 16; ++i) {
    opcodes[string(abi.encodePacked("SWAP", i.toString()))] = 3;
    }

    opcodes["LOG0"] = 375;
    opcodes["LOG1"] = 750;
    opcodes["LOG2"] = 1125;
    opcodes["LOG3"] = 1500;
    opcodes["LOG4"] = 1875;
    opcodes["CREATE"] = 32000;
    opcodes["CALL"] = 100;
    opcodes["CALLCODE"] = 100;
    opcodes["RETURN"] = 0;
    opcodes["DELEGATECALL"] = 100;
    opcodes["CREATE2"] = 32000;
    opcodes["STATICCALL"] = 100;
    opcodes["REVERT"] = 0;
    opcodes["INVALID"] = uint(~0);
    opcodes["SELFDESTRUCT"] = 5000;
    }

    /**
    * @notice Retrieves the gas cost of a specified opcode.
    * @param opcodeName The name of the opcode.
    * @return The gas cost associated with the opcode.
    * @dev Reverts if the opcode does not exist.
    */
    function getGasCost(string memory opcodeName) public view returns (uint) {
    require(opcodes[opcodeName] != 0, "Opcode not found");
    return opcodes[opcodeName];
    }

    /**
    * @notice Calculates the total gas cost for an array of opcode names.
    * @param opcodeNames An array of opcode names.
    * @return totalGasCost The total gas cost for the opcodes.
    * @dev Assumes that all opcode names in the array are valid.
    */
    function getTotalGasCost(string[] memory opcodeNames) public view returns (uint totalGasCost) {
    totalGasCost = 0;
    for (uint i = 0; i < opcodeNames.length; ++i) {
    // Using the existing getGasCost function to retrieve each opcode's gas cost
    totalGasCost += getGasCost(opcodeNames[i]);
    }
    }
    }