{"id":15673997,"url":"https://github.com/sshine/evm-opcodes","last_synced_at":"2026-01-25T13:04:43.047Z","repository":{"id":49538609,"uuid":"252688433","full_name":"sshine/evm-opcodes","owner":"sshine","description":"Opcode types for Ethereum Virtual Machine (EVM)","archived":false,"fork":false,"pushed_at":"2026-01-17T08:40:39.000Z","size":159,"stargazers_count":6,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-17T19:20:22.077Z","etag":null,"topics":["hacktoberfest","haskell"],"latest_commit_sha":null,"homepage":"","language":"Haskell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sshine.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2020-04-03T09:30:58.000Z","updated_at":"2026-01-17T08:40:42.000Z","dependencies_parsed_at":"2024-11-09T07:01:59.972Z","dependency_job_id":"8e53ae11-485b-49d1-8df4-e555eeeabb60","html_url":"https://github.com/sshine/evm-opcodes","commit_stats":{"total_commits":102,"total_committers":2,"mean_commits":51.0,"dds":"0.13725490196078427","last_synced_commit":"0c8fd648782c48715c7747b7766132c327125bc9"},"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/sshine/evm-opcodes","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sshine%2Fevm-opcodes","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sshine%2Fevm-opcodes/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sshine%2Fevm-opcodes/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sshine%2Fevm-opcodes/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sshine","download_url":"https://codeload.github.com/sshine/evm-opcodes/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sshine%2Fevm-opcodes/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28753411,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-25T10:25:12.305Z","status":"ssl_error","status_checked_at":"2026-01-25T10:25:11.933Z","response_time":113,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["hacktoberfest","haskell"],"created_at":"2024-10-03T15:43:21.633Z","updated_at":"2026-01-25T13:04:43.042Z","avatar_url":"https://github.com/sshine.png","language":"Haskell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# evm-opcodes\n\n[![MIT License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](http://opensource.org/licenses/MIT)\n[![Hackage](https://img.shields.io/hackage/v/evm-opcodes.svg?style=flat)](https://hackage.haskell.org/package/evm-opcodes)\n[![Stackage Nightly](http://stackage.org/package/evm-opcodes/badge/nightly)](http://stackage.org/nightly/package/evm-opcodes)\n[![Stackage LTS](http://stackage.org/package/evm-opcodes/badge/lts)](http://stackage.org/lts/package/evm-opcodes)\n[![Haskell CI](https://github.com/sshine/evm-opcodes/actions/workflows/haskell.yml/badge.svg)](https://github.com/sshine/evm-opcodes/actions/workflows/haskell.yml)\n\nThis Haskell library provides opcode types for the Ethereum Virtual Machine (EVM).\n\nThe library has one parameterised type, `Opcode' j` where `j` is the annotation\nfor the jump-related instructions `JUMP`, `JUMPI` and `JUMPDEST`, and it has\nthree concrete variants:\n\n - `type Opcode = Opcode' ()`\n - `type PositionalOpcode = Opcode' Word`\n - `type LabelledOpcode = Opcode' Text`\n\nThe library has a fixpoint algorithm that translates labelled jumps into\npositional jumps, and it has another function that translates those positional\njumps into plain EVM opcodes where a constant is pushed before a jump is made.\n\nThe constant that is pushed depends on the position of `JUMPDEST` which depends\non the constant that is pushed, hence the need for fixpoint iteration.\n\nWhen pushing a constant to the stack, EVM uses `push0`, `push1`, `push2`, ...,\n`push32` where the number 0-32 refers to how many bytes the constant occupies.\nInstead of having 32 unique push commands, this library has a single `PUSH\n!Word256` constructor that serializes to the right `push1`, `push2`, etc.\n\n## Example\n\nImagine translating the following C program to EVM opcodes:\n\n```\nint x = 1;\nwhile (x != 0) { x *= 2 };\n```\n\nSince EVM is stack-based, let's put `x` on the stack.\n\n```haskell\nλ\u003e import EVM.Opcode\nλ\u003e import EVM.Opcode.Labelled as L\nλ\u003e import EVM.Opcode.Positional as P\n\nλ\u003e let opcodes = [PUSH 1,JUMPDEST \"loop\",DUP1,ISZERO,JUMPI \"end\",PUSH 2,MUL,JUMP \"loop\",JUMPDEST \"end\"]\n\nλ\u003e L.translate opcodes\nRight [PUSH 1,JUMPDEST 2,DUP1,ISZERO,JUMPI 14,PUSH 2,MUL,JUMP 2,JUMPDEST 14]\n\nλ\u003e P.translate \u003c$\u003e L.translate opcodes\nRight [PUSH 1,JUMPDEST,DUP1,ISZERO,PUSH 14,JUMPI,PUSH 2,MUL,PUSH 2,JUMP,JUMPDEST]\n\nλ\u003e fmap opcodeText . P.translate \u003c$\u003e L.translate opcodes\nRight [\"push1 1\",\"jumpdest\",\"dup1\",\"iszero\",\"push1 14\",\"jumpi\",\"push1 2\",\"mul\",\"push1 2\",\"jump\",\"jumpdest\"]\n```\n\n## Accounts for size of `PUSH`es when doing absolute jumps\n\nEVM's `jump` and `jumpi` instructions are parameterless. Instead they pop and\njump to the address on the top of the stack. In order to perform absolute jumps\nin the code, it is necessary to `PUSH` an address on the stack first.  This is\ninconvenient, and so `PositionalOpcode` and `LabelledOpcode` are easier to use.\n\nBut what's more inconvenient is what happens to the offset of an absolute jump\nwhen the address being jumped to crosses a boundary where its byte index can no\nlonger be represented by the same amount of bytes.\n\nTake for example this EVM code:\n\n```\n0x00: push1 255\n0x02: jump\n0x03: stop\n0x04: stop\n0x05: stop\n...\n0xfe: stop\n0xff: jumpdest\n```\n\nwhich can be represented with the following `LabelledOpcode`:\n\n```haskell\nλ\u003e import EVM.Opcode\nλ\u003e import EVM.Opcode.Labelled as L\nλ\u003e import EVM.Opcode.Positional as P\n\nλ\u003e let opcodes = [JUMP \"skip\"] \u003c\u003e replicate 252 STOP \u003c\u003e [JUMPDEST \"skip\"]\nλ\u003e fmap (fmap opcodeText . P.translate) (L.translate opcodes)\nRight [\"push1 255\",\"jump\",\"stop\",\"stop\",\"stop\",...,\"jumpdest\"]\n```\n\nNote especially the byte size of a `PUSH 255` vs. a `PUSH 256`:\n\n```haskell\nλ\u003e opcodeSize (PUSH 255)\n2\nλ\u003e opcodeSize (PUSH 256)\n3\n```\n\nThen add another one-byte opcode between the `jump` and the `jumpdest`:\n\n```haskell\nλ\u003e let opcodes = [JUMP \"skip\"] \u003c\u003e replicate 253 STOP \u003c\u003e [JUMPDEST \"skip\"]\nλ\u003e fmap (fmap opcodeText . P.translate) (L.translate opcodes)\nRight [\"push2 257\",\"jump\",\"stop\",\"stop\",\"stop\",...,\"jumpdest\"]\n```\n\nEven though one byte was added, because the address of `jumpdest` is now\ngreater than 255, all references to it now take more than 2 bytes. Concretely,\none reference went from 2 bytes to 3 bytes, or rather, one `JUMP \"skip\"` became\na `push2 257` instead of a `push1 255`. And if there were many such `jump`s,\nthis amounts to a bit of book-keeping.\n\nThis happens at subsequent boundaries as well. While this library handles each\nboundary the same way, it is unlikely to have EVM bytecode of more than a few\nkilobytes at present time.\n\n```haskell\nλ\u003e let opcodes = [JUMP \"skip\"] \u003c\u003e replicate 65532 STOP \u003c\u003e [JUMPDEST \"skip\"]\nλ\u003e fmap (fmap opcodeText . P.translate) (L.translate opcodes)\nRight [\"push3 65537\",\"jump\",\"stop\",\"stop\",\"stop\",...,\"jumpdest\"]\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsshine%2Fevm-opcodes","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsshine%2Fevm-opcodes","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsshine%2Fevm-opcodes/lists"}