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.
EVM Opcodes Solidity library
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]);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment